Skip to content

Instantly share code, notes, and snippets.

@peckpeck
Created January 14, 2015 16:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peckpeck/f556364e84e85f275e98 to your computer and use it in GitHub Desktop.
Save peckpeck/f556364e84e85f275e98 to your computer and use it in GitHub Desktop.
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent root_alive_check
{
vars:
"sites_to_check" slist => { "http://localhost:8080/rudder/api/status", "http://localhost:8080/endpoint/api/status" };
methods:
"any" usebundle => generic_alive_check("${sites_to_check}");
}
bundle agent generic_alive_check(site_to_check)
{
vars:
"sitename" string => canonify("${site_to_check}");
"cleanup_failed_classes" slist => { "site_down_once_${sitename}", "site_alivecheck_restart_jetty_${sitename}" };
"failed_result_class" string => "site_down_once_${sitename}",
ifvarclass => "!site_down_once_${sitename}.!first_iteration_passed";
"site_failure_persist_time" string => "10",
ifvarclass => "!site_down_once_${sitename}.!first_iteration_passed";
"failed_result_class" string => "site_alivecheck_restart_jetty_${sitename}",
ifvarclass => "site_down_once_${sitename}.!first_iteration_passed";
"site_failure_persist_time" string => "0",
ifvarclass => "site_down_once_${sitename}.!first_iteration_passed";
classes:
"first_iteration_passed" expression => "any";
methods:
"any" usebundle => generic_process_check_process(".*java.*/opt/rudder/jetty7/start.jar", "rudder-jetty", "true"),
ifvarclass => "site_alivecheck_restart_jetty_${sitename}",
classes => set_persist_classes("site_alivecheck_jetty_restarted_${sitename}", "site_down_once_${sitename}" ,"0");
commands:
"/usr/bin/curl -s ${site_to_check} |/bin/grep -q OK"
contain => in_shell_silent,
classes => set_persist_classes_alivecheck("site_ok", "${failed_result_class}", "@{generic_alive_check.cleanup_failed_classes}", "${site_failure_persist_time}"),
comment => "Checking if ${site_to_check} is alive";
reports:
linux::
"@@DistributePolicy@@Success@@root-DP#@root-distributePolicy##${g.uuid}@#The ${site_to_check} web application is running"
ifvarclass => "site_ok.!site_down_once_${sitename}";
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#This is the first time the ${site_to_check} web application failed to respond. Deferring the restart."
ifvarclass => "site_down_once_${sitename}.!site_alivecheck_restart_jetty_${sitename}";
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#The ${site_to_check} web application failed to respond for the second time. Restarting rudder-jetty NOW !"
ifvarclass => "site_alivecheck_restart_jetty_${sitename}";
}
body classes set_persist_classes_alivecheck(repaired, failed, cancelifok, length)
{
promise_kept => { "${repaired}" };
promise_repaired => { "${repaired}" };
repair_failed => { "${failed}" };
repair_denied => { "${failed}" };
repair_timeout => { "${failed}" };
cancel_kept => {"@{cancelifok}"};
cancel_repaired => {"@{cancelifok}"};
cancel_notkept => {"${repaired}"};
persist_time => "${length}";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent root_logrotate_check
{
files:
debian::
"/etc/logrotate.d/rudder"
copy_from => copy_digest("${sys.workdir}/inputs/distributePolicy/logrotate.conf/rudder.debian"),
classes => kept_if_else("rudder_logrotate_conf_ok", "rudder_logrotate_conf_copied", "cannot_copy_rudder_logrotate_conf"),
comment => "Copying the logrotate configuration for Debian-like system";
redhat::
"/etc/logrotate.d/rudder"
copy_from => copy_digest("${sys.workdir}/inputs/distributePolicy/logrotate.conf/rudder.rhel"),
classes => kept_if_else("rudder_logrotate_conf_ok", "rudder_logrotate_conf_copied", "cannot_copy_rudder_logrotate_conf"),
comment => "Copying the logrotate configuration for Debian-like system";
!debian.!redhat::
"/etc/logrotate.d/rudder"
copy_from => copy_digest("${sys.workdir}/inputs/distributePolicy/logrotate.conf/rudder.debian"),
classes => kept_if_else("rudder_logrotate_conf_ok", "rudder_logrotate_conf_copied", "cannot_copy_rudder_logrotate_conf"),
comment => "Copying the logrotate configuration for Debian-like system";
reports:
linux::
"@@DistributePolicy@@Success@@root-DP#@root-distributePolicy##${g.uuid}@#The logrotate configuration is correct"
ifvarclass => "rudder_logrotate_conf_ok.!rudder_logrotate_conf_copied.!cannot_copy_rudder_logrotate_conf";
"@@DistributePolicy@@Repaired@@root-DP#@root-distributePolicy##${g.uuid}@#The logrotate configuration has been updated"
ifvarclass => "rudder_logrotate_conf_copied.!cannot_copy_rudder_logrotate_conf";
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#The logrotate configuration could not be updated"
ifvarclass => "cannot_copy_rudder_logrotate_conf";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent root_postgres_check
{
vars:
SuSE::
"configuration_statements" slist => { "host all rudder ::1/128 md5", "host all rudder 127.0.0.1/32 md5" };
commands:
SuSE::
"/etc/init.d/postgresql"
args => "restart",
classes => kept_if_else("psql_restart_ok", "psql_restart_ok", "psql_restart_error"),
ifvarclass => "psql_conf_updated";
files:
SuSE::
"/var/lib/pgsql/data/pg_hba.conf"
edit_line => prepend("${configuration_statements}"),
edit_defaults => noempty_backup,
classes => kept_if_else("psql_conf_ok", "psql_conf_updated", "psql_conf_update_error"),
comment => "Edit the SuSE postgresql configuration to enable account-less logins";
reports:
SuSE::
# Report about the configuration file edition
"@@DistributePolicy@@Success@@root-DP#@root-distributePolicy##${g.uuid}@#The SuSE specific postgresql configuration is present"
ifvarclass => "psql_conf_ok.!psql_conf_updated.!psql_conf_update_error";
"@@DistributePolicy@@Repaired@@root-DP#@root-distributePolicy##${g.uuid}@#The SuSE specific postgresql configuration has been added"
ifvarclass => "psql_conf_updated.!psql_conf_update_error";
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#The SuSE specific postgresql configuration could not be added"
ifvarclass => "psql_conf_update_error";
# Reports about Postgres restart status
"@@DistributePolicy@@Inform@@root-DP#@root-distributePolicy##${g.uuid}@#PostgreSQL has been restarted"
ifvarclass => "psql_restart_ok";
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#PostgreSQL restart has failed! Rudder is most certainly broken..."
ifvarclass => "psql_restart_error";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent root_apache_webdav_check
{
vars:
# I WANT to use this but there is no crypt support... yet
# "dav_password" string => hash("rudder","crypt");
"dav_user[1]" string => "rudder";
"dav_password[1]" string => "PoBZbSkW/8bcE";
"iterator" slist => getindices("dav_user");
debian::
"webdav_check_wwwgroup" string => "www-data";
!debian::
"webdav_check_wwwgroup" string => "www";
files:
"${g.rudder_base}/etc/htpasswd-webdav"
create => "true",
edit_line => insert_lines("${dav_user[${iterator}]}:${dav_password[${iterator}]}"),
edit_defaults => empty_backup,
perms => mog("640", "root", "${webdav_check_wwwgroup}"),
classes => kept_if_else("rudder_apache_davpassword_ok", "rudder_apache_davpassword_changed", "rudder_apache_davpassword_failed"),
comment => "Verifying the Rudder WebDAV user and password";
reports:
linux::
"@@DistributePolicy@@Success@@root-DP#@root-distributePolicy##${g.uuid}@#The Rudder WebDAV user and password are OK"
ifvarclass => "rudder_apache_davpassword_ok.!rudder_apache_davpassword_changed.!rudder_apache_davpassword_failed";
"@@DistributePolicy@@Repaired@@root-DP#@root-distributePolicy##${g.uuid}@#The Rudder WebDAV user and password were updated"
ifvarclass => "rudder_apache_davpassword_changed.!rudder_apache_davpassword_failed";
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#The Rudder WebDAV user and password could not be updated"
ifvarclass => "rudder_apache_davpassword_failed";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
# Path of the promises files on the machine
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent root_ldap_check
{
vars:
"ldap_rudder_user" string => "rudder";
"ldap_rudder_cleartext_password" string => "secret";
# We'd like to generate the password but a strange convergeance bug prevents this. You have to generate the hashed string manually if required.
# "ldap_rudder_hashed_password" string => execresult("/opt/rudder/sbin/slappasswd -s ${ldap_rudder_cleartext_password}", "noshell");
"ldap_rudder_hashed_password" string => "{SSHA}UK0Ut/7QsceF3ZHJl6nXotlEvh8ECzZx";
"ldap_dot_properties" slist => { "${g.rudder_base}/etc/inventory-web.properties", "${g.rudder_base}/etc/rudder-web.properties" };
files:
"${g.rudder_base}/etc/openldap/slapd.conf"
edit_line => ldap_password_slapd("${ldap_rudder_hashed_password}"),
perms => mog("600", "root", "root"),
classes => kept_if_else("rudder_ldap_slapd_password_ok", "rudder_ldap_slapd_password_changed", "rudder_ldap_slapd_password_failed"),
comment => "Verifying the Rudder LDAP password in slapd.conf";
"${ldap_dot_properties}"
edit_line => ldap_password_properties("${ldap_rudder_cleartext_password}"),
perms => mog("600", "root", "root"),
classes => kept_if_else("rudder_ldap_prop_password_ok", "rudder_ldap_prop_password_changed", "rudder_ldap_prop_password_failed"),
comment => "Verifying the Rudder LDAP password in the properties files";
methods:
"any" usebundle => generic_process_check_process("/opt/rudder/libexec/slapd", "rudder-slapd", "true"),
ifvarclass => "rudder_ldap_slapd_password_changed";
"any" usebundle => generic_process_check_process(".*java.*/opt/rudder/jetty7/start.jar", "rudder-jetty", "true"),
ifvarclass => "rudder_ldap_prop_password_changed";
reports:
linux::
# slapd configuration
"@@DistributePolicy@@Success@@root-DP#@root-distributePolicy##${g.uuid}@#The Rudder OpenLDAP daemon password is OK"
ifvarclass => "rudder_ldap_slapd_password_ok.!rudder_ldap_slapd_password_changed.!rudder_ldap_slapd_password_failed";
"@@DistributePolicy@@Repaired@@root-DP#@root-distributePolicy##${g.uuid}@#The Rudder OpenLDAP daemon password has been updated"
ifvarclass => "rudder_ldap_slapd_password_changed.!rudder_ldap_slapd_password_failed";
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#The Rudder OpenLDAP daemon password failed to update"
ifvarclass => "rudder_ldap_slapd_password_failed";
# properties configuration
"@@DistributePolicy@@Success@@root-DP#@root-distributePolicy##${g.uuid}@#The Rudder LDAP properties files passwords are OK"
ifvarclass => "rudder_ldap_prop_password_ok.!rudder_ldap_prop_password_changed.!rudder_ldap_prop_password_failed";
"@@DistributePolicy@@Repaired@@root-DP#@root-distributePolicy##${g.uuid}@#The Rudder LDAP properties files passwords were updated"
ifvarclass => "rudder_ldap_prop_password_changed.!rudder_ldap_prop_password_failed";
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#The Rudder LDAP properties files passwords failed to update"
ifvarclass => "rudder_ldap_prop_password_failed";
}
bundle edit_line ldap_password_slapd(password)
{
delete_lines:
"rootpw.*";
insert_lines:
"rootpw ${password}"
location => after("rootdn.*");
}
bundle edit_line ldap_password_properties(password)
{
delete_lines:
"ldap.authpw.*";
insert_lines:
"ldap.authpw=${password}"
location => after("ldap.authdn.*");
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent root_integrity_check
{
files:
"${g.rudder_var}/configuration-repository"
create => "true",
action => WarnOnly,
classes => if_else("rudder_integrity_ok", "rudder_integrity_failed");
reports:
linux::
"@@DistributePolicy@@Success@@root-DP#@root-distributePolicy##${g.uuid}@#The ${g.rudder_var}/configuration-repository directory is present"
ifvarclass => "rudder_integrity_ok.!rudder_integrity_failed";
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#EMERGENCY: THE ${g.rudder_var}/configuration-repository DIRECTORY IS *ABSENT*. THIS ORCHESTRATOR WILL *NOT* OPERATE CORRECTLY."
ifvarclass => "!rudder_integrity_ok|rudder_integrity_failed";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
# Configure rsyslog on the orchestrator
# This will provide promises to add the backports repos to Debian Lenny:
# - in sources.list
# - default apt_preferences to upgrade packages installed from backports
# - a package_method to install packages from backports via cfengine
bundle agent setup_debian_backports
{
vars:
"apt_source_line" slist => { "deb http://backports.debian.org/debian-backports lenny-backports" };
"apt_components" slist => { "main" };
files:
debian_5::
"/etc/apt/sources.list"
comment => "Include extra apt repos",
edit_line => append_if_no_lines("${apt_source_line} ${apt_components}"),
edit_defaults => noempty_backup,
classes => if_repaired("apt_sources_updated");
"/etc/apt/preferences"
comment => "Set automatic upgrades for packages installed from backports (recommended setting from backports.debian.org)",
create => "true",
edit_line => append_if_no_lines("Package: *${const.n}Pin: release a=lenny-backports${const.n}Pin-Priority: 200"),
edit_defaults => noempty_backup,
classes => if_repaired("apt_preferences_repaired");
commands:
apt_sources_updated::
"/usr/bin/aptitude"
args => "update";
reports:
apt_sources_updated::
"apt's sources.list was edited, and an aptitude update will now run";
apt_preferences_repaired::
"apt's /etc/apt/preferences file was changed";
}
bundle agent install_rsyslogd
{
packages:
policy_server.debian_5.!SuSE::
"rsyslog"
package_policy => "add",
package_method => debian_backports,
classes => cf2_if_else("rsyslog_installed", "cant_install_rsyslog"),
comment => "Installing rsyslog using apt backports";
"rsyslog-pgsql"
package_policy => "add",
package_method => debian_backports,
classes => cf2_if_else("rsyslog_pgsql_installed", "cant_install_rsyslog_pgsql"),
comment => "Installing rsyslog_pgsql using apt backports";
policy_server.!debian_5.!SuSE::
"rsyslog"
package_policy => "add",
package_method => generic,
classes => cf2_if_else("rsyslog_installed", "cant_install_rsyslog"),
comment => "Installing rsyslog using apt backports";
"rsyslog-pgsql"
package_policy => "add",
package_method => generic,
classes => cf2_if_else("rsyslog_pgsql_installed", "cant_install_rsyslog_pgsql"),
comment => "Installing rsyslog_pgsql using apt backports";
files:
policy_server::
"/etc/rsyslog.d/rudder.conf"
copy_from => copy_digest("${sys.workdir}/inputs/distributePolicy/rsyslog.conf/rudder.conf"),
classes => cf2_if_else("rudder_rsyslog_conf_copied", "cannot_copy_rudder_rsyslog_conf"),
comment => "Copying rsyslog conf";
"/etc/rsyslog.conf"
edit_line => append_if_no_lines("$IncludeConfig /etc/rsyslog.d/*.conf"),
edit_defaults => noempty_backup,
comment => "Add the rsyslog.conf.d include if not already present",
classes => cf2_if_else("rsyslog_inc_ok" , "rsyslog_inc_failed");
policy_server.!SuSE::
"/etc/rsyslog.d/pgsql.conf"
edit_line => comment_all(),
edit_defaults => noempty_backup,
classes => cf2_if_else("rudder_rsyslog_pgsql", "cannot_update_rudder_rsyslog_pgsql"),
comment => "Removing the logging of all in the database";
commands:
policy_server.(rsyslog_installed|rsyslog_pgsql_installed|rudder_rsyslog_conf_copied|rudder_rsyslog_pgsql).!SuSE::
"/etc/init.d/rsyslog"
args => "restart",
classes => cf2_if_else("rsyslog_restarted", "cant_restart_rsyslog"),
comment => "restarting rsyslog";
policy_server.(rsyslog_installed|rsyslog_pgsql_installed|rudder_rsyslog_conf_copied|rudder_rsyslog_pgsql).SuSE::
"/etc/init.d/syslog"
args => "restart",
classes => cf2_if_else("rsyslog_restarted", "cant_restart_rsyslog"),
comment => "restarting rsyslog";
reports:
cant_install_rsyslog|cant_install_rsyslog_pgsql::
"Fatal : Can't install rsyslog or rsyslog_pgsql on the Rudder root server !";
cannot_copy_rudder_rsyslog_conf::
"Fatal : Can't copy the rsyslog configuration !";
rsyslog_inc_failed::
"Fatal : Can't enable the rsyslog include directory !";
cant_restart_rsyslog::
"Fatal : Can't restart rsyslog !";
cannot_update_rudder_rsyslog_pgsql::
"Fatal : Cannot update the pgsql configuration !";
rsyslog_restarted::
"Info : Restarted rsyslog";
}
# Package method to install packages from debian-backports
body package_method debian_backports
{
debian::
package_changes => "bulk";
package_list_command => "/usr/bin/dpkg -l";
package_list_name_regex => "ii\s+([^\s]+).*";
package_list_version_regex => "ii\s+[^\s]+\s+([^\s]+).*";
package_installed_regex => ".*"; # all reported are installed
package_name_convention => "${name}";
package_list_update_ifelapsed => "240"; # 4 hours
debian.have_aptitude::
package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o Aptitude::Delete-Unused=false -t lenny-backports --assume-yes install";
package_list_update_command => "/usr/bin/aptitude update";
package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o Aptitude::Delete-Unused=false --assume-yes -q remove";
package_update_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o Aptitude::Delete-Unused=false --assume-yes install";
package_verify_command => "/usr/bin/aptitude show";
package_noverify_regex => "(State: not installed|E: Unable to locate package .*)";
debian.!have_aptitude::
package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o APT::Get::AutomaticRemove=false --yes -t lenny-backports install";
package_list_update_command => "/usr/bin/apt-get update";
package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o APT::Get::AutomaticRemove=false --yes -q remove";
package_update_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o APT::Get::AutomaticRemove=false --yes install";
package_verify_command => "/usr/bin/dpkg -s";
package_noverify_returncode => "1";
}
bundle edit_line comment_all()
{
replace_patterns:
# comment all lines
"^[^#](.*)"
replace_with => comments;
}
body replace_with comments
{
replace_value => "#${match.1}"; # backreference 0
occurrences => "all"; # first, last all
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent root_init_check()
{
vars:
"service[1][binary]" string => "/opt/rudder/libexec/slapd";
"service[1][initscript]" string => "rudder-slapd";
"service[2][binary]" string => ".*java.*/opt/rudder/jetty7/start.jar";
"service[2][initscript]" string => "rudder-jetty";
"service[3][binary]" string => "postgres: writer process";
"service[3][initscript]" string => "postgresql";
"service[4][binary]" string => "/var/cfengine/bin/cf-.*";
"service[4][initscript]" string => "cfengine3";
"service[5][binary]" string => "apache2";
"service[5][initscript]" string => "apache2";
"index" slist => getindices("service");
methods:
"any" usebundle => generic_process_check_process("${service[${index}][binary]}", "${service[${index}][initscript]}", "false");
"any" usebundle => generic_process_check_bootstart("${service[${index}][binary]}", "${service[${index}][initscript]}");
}
bundle agent generic_process_check_process(binary, initscript, force_restart)
{
vars:
"canoname" string => canonify("${binary}");
classes:
"forced_trigger_${canoname}" expression => strcmp("${force_restart}", "true");
processes:
# check the service status
"${binary}"
comment => "Check the process status",
restart_class => "process_restart_${canoname}",
classes => kept_if_else("service_running_${canoname}", "service_anomaly_${canoname}", "service_error_${canoname}");
commands:
"/etc/init.d/${initscript}"
args => "restart </dev/null >/dev/null 2>/dev/null",
contain => in_shell_silent,
# action => bg("0", "120"),
classes => kept_if_else("process_restart_ok_${canoname}", "process_restart_ok_${canoname}", "process_restart_error_${canoname}"),
ifvarclass => "process_restart_${canoname}|forced_trigger_${canoname}";
reports:
linux::
"@@DistributePolicy@@Success@@root-DP#@root-distributePolicy##${g.uuid}@#The ${initscript} process is already running"
ifvarclass => "!process_restart_${canoname}.!forced_trigger_${canoname}";
"@@DistributePolicy@@Repaired@@root-DP#@root-distributePolicy##${g.uuid}@#The ${initscript} process was not running and has been restarted"
ifvarclass => "process_restart_${canoname}.process_restart_ok_${canoname}.!forced_trigger_${canoname}";
"@@DistributePolicy@@Repaired@@root-DP#@root-distributePolicy##${g.uuid}@#The ${initscript} process has been restarted"
ifvarclass => "process_restart_ok_${canoname}.forced_trigger_${canoname}";
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#The ${initscript} process couldn't be restarted"
ifvarclass => "process_restart_error_${canoname}";
}
bundle agent generic_process_check_bootstart(binary, initscript)
{
vars:
"canoname" string => canonify("${binary}");
commands:
(SuSE|redhat)::
"/sbin/chkconfig"
args => "--check ${initscript}",
classes => if_else("service_bootstarted_${canoname}", "service_unbootstarted_${canoname}"),
comment => "Check if the service ${initscript} is started on boot";
"/sbin/insserv"
args => "-d ${initscript}",
classes => if_else("service_bootstarted_ok_${canoname}", "service_bootstarted_fail_${canoname}"),
ifvarclass => "service_unbootstarted_${canoname}",
comment => "Set the service ${initscript} to start on boot";
debian::
"/usr/sbin/update-rc.d ${initscript} remove \&\& /usr/sbin/update-rc.d ${initscript} defaults"
contain => in_shell,
classes => if_else("service_bootstarted_ok_${canoname}", "service_bootstarted_fail_${canoname}"),
ifvarclass => "service_unbootstarted_${canoname}",
comment => "Set the service ${initscript} to start on boot";
files:
debian::
"/etc/rc2.d/S.*${initscript}.*"
create => "true",
action => WarnOnly,
classes => if_else("service_bootstarted_${canoname}", "service_unbootstarted_${canoname}");
reports:
linux::
"@@DistributePolicy@@Success@@root-DP#@root-distributePolicy##${g.uuid}@#${initscript} is started on boot as required"
ifvarclass => "service_bootstarted_${canoname}";
"@@DistributePolicy@@Repaired@@root-DP#@root-distributePolicy##${g.uuid}@#${initscript} has been set to start on boot"
ifvarclass => "!service_bootstarted_${canoname}.service_bootstarted_ok_${canoname}";
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#Could not set ${initscript} to start on boot!"
ifvarclass => "!service_bootstarted_${canoname}.service_bootstarted_fail_${canoname}";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#
# Fetch the promises from the server to be available for others machines
# Must not do it on the RootServer though...
bundle agent propagatePromises
{
vars:
any::
"server_data" string => "${server_info.policy_files}/share"; #actual directory with data to propagate
"client_data" string => "/var/rudder/share/"; #where to put the files on the client when downloaded
files:
root_server::
"${g.rudder_tools}"
copy_from => copy("${g.rudder_base}/share/tools"),
depth_search => recurse_visible("inf"),
comment => "Fetching the tools for the promises execution",
classes => if_else("tools_propagated", "could_not_propagate_tools");
!root_server::
"${client_data}" #that's a loop on each files in client_inputs
copy_from => remote("${server_info.cfserved}","${server_data}"),
depth_search => recurse_visible("inf"),
comment => "Fetching the promises to propagate",
classes => if_else("promises_propagated", "could_not_propagate_promise");
"${g.rudder_tools}"
copy_from => remote("${server_info.cfserved}","${g.rudder_tools}"),
depth_search => recurse_visible("inf"),
comment => "Fetching the tools for the promises execution",
classes => if_else("tools_propagated", "could_not_propagate_tools");
"${sys.workdir}/masterfiles"
copy_from => remote("${server_info.cfserved}","${sys.workdir}/masterfiles"),
depth_search => recurse_visible("inf"),
file_select => no_license_dat, #We don't want to propagate a wrong license.dat
comment => "Fetching the bootstrap promises",
classes => if_else("masterfiles_propagated", "could_not_propagate_masterfiles");
"${sys.workdir}/masterfiles/license.dat"
copy_from => local_cp("${sys.workdir}/inputs/license.dat"),
comment => "Putting the right license in the bootstrap",
classes => if_else("license_copied", "could_not_copy_license");
reports:
could_not_propagate_promise::
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#Cannot propagate policy files";
could_not_propagate_tools::
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#Cannot propagate tools";
could_not_propagate_masterfiles::
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#Cannot propagate masterfiles";
could_not_copy_license::
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#Cannot copy local license";
}
# Sending the inventory to cmdb (or syncing with the server if we are a simple relay)
bundle agent sendInventoryToCmdb
{
files:
root_server::
"${g.rudder_inventories}/incoming"
transformer => "${g.rudder_tools}/send-clean.sh http://localhost:8080/endpoint/upload/ ${this.promiser} ${g.rudder_inventories}/received/ ${g.rudder_inventories}/failed/",
depth_search => recurse_visible(1),
file_select => all_files,
classes => if_else("inventory_sent", "cant_send_inventory"),
comment => "Sending the inventory to the cmdb";
# NEED TO DO THE RSYNC PART
reports:
inventory_sent::
"@@DistributePolicy@@Success@@root-DP#@root-distributePolicy##${g.uuid}@#The inventory has been successfully added to the cmdb";
cant_send_inventory::
"@@DistributePolicy@@Error@@root-DP#@root-distributePolicy##${g.uuid}@#Could not send the inventory to the cmdb";
}
body file_select all_files
{
leaf_name => { ".*\..*" };
file_result => "leaf_name";
}
body file_select no_license_dat
{
leaf_name => { "license\.dat" };
file_result => "!leaf_name";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#######################################################
#
# promises.cf
#
#######################################################
body common control
{
inputs => {
"common/site.cf", "common/update.cf", "common/process_matching.cf", "common/cfengine_stdlib.cf","common/cf-served.cf","common/library.cf","common/core-lib.cf", "common/rudder_stdlib.cf", "distributePolicy/propagatePromises.cf", "distributePolicy/rsyslogConf.cf", "distributePolicy/initCheck.cf", "distributePolicy/postgresCheck.cf", "distributePolicy/logrotateCheck.cf", "distributePolicy/integrityCheck.cf", "distributePolicy/apacheCheck.cf", "distributePolicy/ldapCheck.cf", "distributePolicy/aliveCheck.cf"
};
bundlesequence => { @{va.bs} , "setup_debian_backports", "install_rsyslogd", "propagatePromises", "sendInventoryToCmdb", "root_init_check", "root_postgres_check", "root_logrotate_check", "root_integrity_check", "root_apache_webdav_check", "root_ldap_check", "root_alive_check" };
output_prefix => "rudder";
}
bundle common va
{
vars:
"bs" slist => { "clean_red_button", "set_red_button", "update", "process_matching", "check_cf_processes", "check_uuid"
#, "executor"
};
# definition of the machine roles
classes:
"root_server" expression => "any";
"policy_server" expression => "any";
}
##########################################################
# Red Button part.
# When the file ${sys.workdir}/inputs/stop exists, we must stop the
# execution of the agent on all client machines
##########################################################
bundle agent clean_red_button()
{
commands:
safe.policy_server::
"${sys.workdir}/bin/cf-runagent"
args => "-Dsafe",
comment => "Propagate the safe information to children";
files:
safe.policy_server::
"${g.rudder_var}/share/[a-f0-9A-F\-]+/rules/cfengine-(community|nova)/stopFile"
delete => tidy,
comment => "Deleting the stop file on clients promises, cfengine is good to go";
safe.!policy_server::
"${sys.workdir}/inputs/stopFile"
delete => tidy,
comment => "Deleting the stop file, cfengine is good to go";
reports:
safe::
"@@Common@@Inform@@hasPolicyServer-root#@common-root##${g.uuid}@#Authorizing Cfengine to restart";
}
bundle agent set_red_button()
{
classes:
policy_server::
"danger" expression => fileexists("${g.rudder_var}/share/root/stopFile");
methods:
danger::
"any" usebundle => setStopFile;
danger.policy_server::
"any" usebundle => stopClients;
}
bundle agent setStopFile
{
files:
danger.!policy_server::
"${sys.workdir}/inputs/stop"
create => "true";
danger.policy_server::
"${g.rudder_var}/share/[a-f0-9A-F\-]+/rules/cfengine-(community|nova)/stopFile"
create => "true";
reports:
danger.!policy_server::
"@@Common@@Inform@@hasPolicyServer-root#@common-root##${g.uuid}@#Creating stop file";
danger.policy_server::
"@@Common@@Inform@@hasPolicyServer-root#@common-root##${g.uuid}@#Creating stop files for clients";
}
bundle agent stopClients
{
classes:
policy_server::
"danger" expression => fileexists("${g.rudder_var}/share/root/stopFile");
commands:
danger.policy_server::
"${sys.workdir}/bin/cf-runagent"
args => "-Ddanger",
comment => "Propagate the danger information to children";
reports:
danger.policy_server::
"@@Common@@Inform@@hasPolicyServer-root#@common-root##${g.uuid}@#gStopping all Cfengine operation";
}
bundle agent check_red_button_status()
{
classes:
!policy_server::
"should_not_continue" expression => fileexists("${sys.workdir}/inputs/stopFile");
}
###################################################
# Check that CFengine services are up
###################################################
bundle agent check_cf_processes
{
processes:
"${sys.workdir}/bin/cf-serverd" restart_class => "start_server";
"${sys.workdir}/bin/cf-execd" restart_class => "start_executor";
commands:
start_server::
"${sys.cf_serverd}",
action => u_ifwin_bg,
classes => outcome("server");
start_executor::
"${sys.cf_execd}",
action => u_ifwin_bg,
classes => outcome("executor");
}
#######################################################
# UUID file enforcing
bundle agent check_uuid
{
files:
"${g.uuid_file}"
create => "true",
edit_line => enforce_content("${g.uuid}"),
edit_defaults => empty_backup,
perms => m("644"),
comment => "Setting the uuid variable in a machine";
}
#######################################################
body agent control
{
# if default runtime is 5 mins we need this for long jobs
ifelapsed => "1";
#define here some environment variables
environment => { "DEBIAN_FRONTEND=noninteractive" };
agentfacility => "LOG_LOCAL6";
}
#######################################################
body executor control
{
splaytime => "1";
exec_command => "${sys.workdir}/bin/cf-agent -f failsafe.cf && ${sys.workdir}/bin/cf-agent";
schedule => { "Min00", "Min05", "Min10", "Min15", "Min20", "Min25", "Min30", "Min35", "Min40", "Min45", "Min50", "Min55" };
executorfacility => "LOG_DAEMON";
}
# Not currently used
bundle agent executor
{
# processes:
# linux.!nova_edition::
# "cf-execd"
# restart_class => "start_cfexecd"; #call a class
# commands:
# start_cfexecd:: #define a class
# "/var/cfengine/bin/cf-execd";l
files:
linux.!nova_edition::
"${g.crontab}"
create => "true",
edit_line => upgrade_cfexecd;
}
########################################################
# Not currently used
bundle edit_line upgrade_cfexecd
{
classes:
"exec_fix" not => regline(".*cf-execd.*","${edit.filename}");
insert_lines:
exec_fix::
"0,5,10,15,20,25,30,35,40,45,50,55 * * * * /var/cfengine/bin/cf-execd -F";
reports:
exec_fix::
"Added a 5 minute schedule to crontabs to verify cf-execd is up";
}
#######################################################
body reporter control
{
reports => { "classes", "audit", "all_locks", "hashes", "performance", "last_seen", "monitor_history" };
build_directory => "${sys.workdir}/reports";
report_output => "xml";
}
#######################################################
#Enforce that the file only contains this information
bundle edit_line enforce_content(str)
{
delete_lines:
"${str}" not_matching => "true";
insert_lines:
"${str}";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
# Path of the promises files on the machine
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#
# Failsafe file
#
body common control
{
bundlesequence => { "init_files", "update" };
inputs => { "common/update.cf" };
}
bundle common g
{
vars:
linux|cygwin::
"rudder_base" string => "/opt/rudder";
"rudder_var" string => "/var/rudder";
"rudder_bin" string => "${rudder_base}/bin";
"rudder_sbin" string => "${rudder_base}/sbin";
"rudder_base_sbin" string => "${rudder_base}/sbin"; #folder where tools are installed
"rudder_tools" string => "${rudder_var}/tools";
"rudder_ncf" string => "${rudder_var}/ncf";
any::
"excludedreps" slist => { "\.X11", ".*kde.*", "\.svn", "perl" };
"rudder_tools_origin" string => "/var/rudder/tools";
"rudder_ncf_origin_common" string => "/usr/share/ncf/tree";
"rudder_ncf_origin_local" string => "/var/rudder/configuration-repository/ncf";
"uuid" string => "root";
# definition of the machine roles
classes:
"root_server" expression => "any";
"policy_server" expression => "any";
}
############################################
#generate a key if not present
bundle agent init_files
{
vars:
"components" slist => { "cf-agent", "cf-serverd", "cf-execd", "cf-monitord", "cf-promises", "cf-runagent", "cf-key", "cf-hub" };
nova_edition::
"cfengine_install_path" string => "/usr/local";
community_edition::
"cfengine_install_path" string => "/opt/rudder";
classes:
"missing_key" not => fileexists("${sys.workdir}/ppkeys/localhost.priv");
files:
linux|cygwin::
"${sys.workdir}/bin/${components}"
perms => u_p("700"),
copy_from => cp("${cfengine_install_path}/bin/${components}","localhost"),
action => immediate;
commands:
cygwin.missing_key::
"${sys.workdir}/bin/cf-key.exe";
windows.missing_key.!cygwin::
"\"${sys.workdir}\bin\cf-key\"";
linux.missing_key::
"${sys.workdir}/bin/cf-key";
}
body depth_search recurse(d)
{
depth => "${d}";
}
#perms validation
body perms u_p(p)
{
mode => "${p}";
}
#server may be a list
body copy_from cp(from,server)
{
servers => { "${server}" };
source => "${from}";
compare => "digest";
community_edition::
portnumber => "5309";
}
body action immediate
{
ifelapsed => "0";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#######################################################
#
# Site specific promises
#
#######################################################
bundle common g
{
vars:
SuSE::
"crontab" string => "/var/spool/cron/tabs/root";
!SuSE::
"crontab" string => "/var/spool/cron/crontabs/root";
windows::
"rudder_base" string => "${sys.winprogdir}\Rudder";
"rudder_bin" string => "${rudder_base}\bin";
"rudder_sbin" string => "${rudder_base}\sbin";
"rudder_var" string => "${sys.winprogdir}\Rudder\var";
"rudder_var_tmp" string => "${rudder_var}\tmp"; # tmp generated data
"rudder_base_sbin" string => "${rudder_base}\sbin"; #folder where tools are installed
"rudder_inventories" string => "${rudder_var}\inventories";
"rudder_base_sbin_arg" string => "${sys.winprogdir}\Rudder\sbin"; # for the installer command line
"rudder_ncf" string => "${rudder_var}\ncf";
# DEPRECATED: This variable is used in pre-2.9 Techniques.
"rudder_dependencies" string => "${rudder_sbin}";
windows.!cygwin::
"cfengine_share_directory" string => "c:\opt\hive\cf-served";
"uuid_file" string => "${rudder_base}\uuid.hive";
linux|cygwin::
"rudder_base" string => "/opt/rudder";
"rudder_var" string => "/var/rudder";
"rudder_bin" string => "${rudder_base}/bin";
"rudder_sbin" string => "${rudder_base}/sbin";
"rudder_var_tmp" string => "${rudder_var}/tmp"; # tmp generated data
"rudder_base_sbin" string => "${rudder_base}/sbin"; #folder where tools are installed
"rudder_inventories" string => "${rudder_var}/inventories";
"uuid_file" string => "${rudder_base}/etc/uuid.hive";
"rudder_ncf" string => "${rudder_var}/ncf";
# DEPRECATED: This variable is used in pre-2.9 Techniques.
"rudder_dependencies" string => "${rudder_var}/tools";
any::
"uuid" string => "root";
"server_shares_folder" string => "/var/rudder/share/${uuid}/share";
"rudder_tools" string => "/var/rudder/tools";
"rudder_ncf_origin_common" string => "/usr/share/ncf/tree";
"rudder_ncf_origin_local" string => "/var/rudder/configuration-repository/ncf";
# DEPRECATED: This variable is used in pre-2.9 Techniques.
"rudder_dependencies_origin" string => "/var/rudder/tools";
}
#####################################################################################
# Copyright 2012 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#
# Rudder Promise Body and Bundle Library
#
# This library includes standardized bundles and bodies to be used as part of the
# "best practices" in the Techniques writing
#
##################################################
# classes body
##################################################
#
# Automatically defines classes bases on a given prefix
# The classes are defined based on the romises outcome
#
body classes rudder_common_classes(prefix)
{
promise_kept => { "${prefix}_kept" };
promise_repaired => { "${prefix}_repaired" };
repair_failed => { "${prefix}_failed" , "${prefix}_error" };
repair_denied => { "${prefix}_denied" , "${prefix}_error" };
repair_timeout => { "${prefix}_timeout", "${prefix}_error" };
}
##################################################
# files bundles
##################################################
#
# Insert the standard Rudder disclaimer into a file
#
bundle edit_line rudder_common_disclaimer
{
insert_lines:
"#############################################################
### This file is protected by your Rudder infrastructure. ###
### Manually editing the file might lead your Rudder ###
### infrastructure to change back the server's ###
### configuration and/or to raise a compliance alert. ###
#############################################################
"
location => start,
insert_type => "preserve_block";
}
#
# Select files older than X months
#
body file_select rudder_common_months_old(months)
{
mtime => irange(0,ago(0,"${months}",0,0,0,0));
file_result => "mtime";
}
#
# Select files older than X days
#
body file_select rudder_common_days_old(days)
{
mtime => irange(0,ago(0,0,"${days}",0,0,0));
file_result => "mtime";
}
#
# Select files older than X hours
#
body file_select rudder_common_hours_old(hours)
{
mtime => irange(0,ago(0,0,0,"${hours}",0,0));
file_result => "mtime";
}
#
# Select files older than X minutes
#
body file_select rudder_common_minutes_old(minutes)
{
mtime => irange(0,ago(0,0,0,0,"${minutes}",0));
file_result => "mtime";
}
################################################
# Reporting bundles
################################################
#
# Create and send a report to the server
# This bundle takes 6 parameters :
# technique_name : the name of the technique, human readable
# status : the status of the Component, among the following values
# result_success
# result_error
# result_repaired
# log_repaired (for logging only)
# log_warn (for logging only)
# log_info (for logging only)
# log_debug (for logging only)
# log_trace (for logging only)
# identifier : the identifier of the current Rule and Directive
# component_name : the name of the component within the Technique
# component_key : the value of the component reference variable (or None if undefined)
# message : An explanation message understandable by a human
#
bundle agent rudder_common_report(technique_name, status, identifier, component_name, component_key, message)
{
reports:
cfengine_3::
"@@${technique_name}@@${status}@@${identifier}@@${component_name}@@${component_key}@@${g.execRun}##${g.uuid}@#${message}";
}
#
# Automatically create reports based on existing classes starting by
# class_prefix (as defined by the body classes rudder_common_classes)
# Takes 6 parameters
# technique_name : the name of the technique, human readable
# class_prefix : the prefix of a set of classes to reporting on (suffixes with "kept", "repaired" or "error")
# identifier : the identifier of the current Rule and Directive
# component_name : the name of the component within the Technique
# component_key : the value of the component reference variable (None if it does not exists)
# message_prefix : The begining of an explanation message understandable by a human
#
bundle agent rudder_common_reports_generic(technique_name, class_prefix, identifier, component_name, component_key, message_prefix)
{
methods:
"success"
usebundle => rudder_common_report("${technique_name}", "result_success", "${identifier}", "${component_name}", "${component_key}", "${message_prefix} was correct"),
ifvarclass => "${class_prefix}_kept.!${class_prefix}_repaired.!${class_prefix}_error";
"repaired"
usebundle => rudder_common_report("${technique_name}", "result_repaired", "${identifier}", "${component_name}", "${component_key}", "${message_prefix} was repaired"),
ifvarclass => "${class_prefix}_repaired.!${class_prefix}_error";
"error"
usebundle => rudder_common_report("${technique_name}", "result_error", "${identifier}", "${component_name}", "${component_key}", "${message_prefix} could not be repaired"),
ifvarclass => "${class_prefix}_error";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
###########################################################################
# Copyright (C) Cfengine AS
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# To the extent this program is licensed as part of the Enterprise
# versions of Cfengine, the applicable Commerical Open Source License
# (COSL) may apply to this file if you as a licensee so wish it. See
# included file COSL.txt.
###########################################################################
#
# Cfengine Community Open Promise-Body Library
#
# This initiative started by Cfengine promotes a
# standardized set of names and promise specifications
# for template functionality within Cfengine 3.
#
# The aim is to promote an industry standard for
# naming of configuration patterns, leading to a
# de facto middleware of standardized syntax.
#
# Names should be intuitive and parameters should be
# minimal to assist readability and comprehensibility.
# Contributions to this file are voluntarily given to
# the cfengine community, and are moderated by Cfengine.
# No liability or warranty for misuse is implied.
#
# If you add to this file, please try to make the
# contributions "self-documenting". Comments made
# after the bundle/body statement are retained in
# the online docs
#
# Subversion : $Rev: 71 $
# For Cfengine Core: 3.1.0
###################################################
# If you find Cfengine useful, please consider #
# purchasing a commercial version of the software.#
###################################################
###################################################
# edit_line bundles
###################################################
bundle edit_line insert_lines(lines)
{
insert_lines:
"${lines}"
comment => "Append lines if they don't exist";
}
##
bundle edit_line comment_lines_matching(regex,comment)
# Comment lines of a file matching a regex
{
replace_patterns:
"^(${regex})$"
replace_with => comment("${comment}"),
comment => "Search and replace string";
}
##
bundle edit_line uncomment_lines_matching(regex,comment)
# Uncomment lines of a file where the regex matches
# the text after the comment string
{
replace_patterns:
"^${comment}\s?(${regex})$"
replace_with => uncomment,
comment => "Uncomment lines matching a regular expression";
}
##
bundle edit_line comment_lines_containing(regex,comment)
# Comment lines of a file containing a regex
{
replace_patterns:
"^(.*${regex}.*)$"
replace_with => comment("${comment}"),
comment => "Comment out lines in a file";
}
##
bundle edit_line uncomment_lines_containing(regex,comment)
# Uncomment lines of a file where the regex matches
# the text after the comment string
{
replace_patterns:
"^${comment}\s?(.*${regex}.*)$"
replace_with => uncomment,
comment => "Uncomment a line containing a fragment";
}
##
bundle edit_line delete_lines_matching(regex)
{
delete_lines:
"${regex}"
comment => "Delete lines matching regular expressions";
}
##
bundle edit_line warn_lines_matching(regex)
{
delete_lines:
"${regex}"
comment => "Warn about lines in a file",
action => warn_only;
}
##
bundle edit_line append_if_no_line(str)
{
insert_lines:
"${str}"
comment => "Append a line to the file if it doesn't already exist";
}
##
bundle edit_line append_if_no_lines(list)
{
insert_lines:
"${list}"
comment => "Append lines to the file if they don't already exist";
}
##
bundle edit_line resolvconf(search,list)
# search is the search domains with space
# list is an slist of nameserver addresses
{
delete_lines:
"search.*" comment => "Reset search lines from resolver";
"nameserver.*" comment => "Reset nameservers in resolver";
insert_lines:
"search ${search}" comment => "Add search domains to resolver";
"nameserver ${list}" comment => "Add name servers to resolver";
}
##
bundle edit_line set_variable_values(v)
# Sets the RHS of variables in the file of the form
# LHS = RHS
# Adds a new line if no LHS exists, repairs RHS values if one does exist
#
# To use:
# 1) Define an array, where the keys are the LHS and the values are the RHS
# "stuff[lhs-1]" string => "rhs1";
# "stuff[lhs-2]" string => "rhs2";
# 2) The parameter passed to the edit_line promise is the fully qualified
# name of the array (i.e., "bundlename.stuff") WITHOUT any "$" or "@"
{
vars:
"index" slist => getindices("${v}");
# Be careful if the index string contains funny chars
"cindex[${index}]" string => canonify("${index}");
field_edits:
# match a line starting like the key = something
"\s*${index}\s*=.*"
edit_field => col("=","2","$(${v}[${index}])","set"),
classes => if_ok("$(cindex[${index}])_in_file"),
comment => "Match a line starting like key = something";
insert_lines:
"${index}=$(${v}[${index}])",
comment => "Insert a variable definition",
ifvarclass => "!$(cindex[${index}])_in_file";
}
##
bundle edit_line append_users_starting(v)
# For adding to /etc/passwd or etc/shadow, needs
# an array v[username] string => "line..."
{
vars:
"index" slist => getindices("${v}");
classes:
"add_${index}" not => userexists("${index}");
insert_lines:
"$(${v}[${index}])",
comment => "Append users into a password file format",
ifvarclass => "add_${index}";
}
##
bundle edit_line append_groups_starting(v)
# For adding groups to /etc/group, needs
# an array v[groupname] string => "line..."
{
vars:
"index" slist => getindices("${v}");
classes:
"add_${index}" not => groupexists("${index}");
insert_lines:
"$(${v}[${index}])",
comment => "Append users into a group file format",
ifvarclass => "add_${index}";
}
##
bundle edit_line set_user_field(user,field,val)
# Set the value of field number "field" in
# a :-field formatted file like /etc/passwd
{
field_edits:
"${user}:.*"
comment => "Edit a user attribute in the password file",
edit_field => col(":","${field}","${val}","set");
}
##
bundle edit_line append_user_field(group,field,allusers)
# For adding users to to a file like /etc/group
# at field position "field", comma separated subfields
{
vars:
"val" slist => { @{allusers} };
field_edits:
"${group}:.*"
comment => "Append users into a password file format",
edit_field => col(":","${field}","${val}","alphanum");
}
##
bundle edit_line expand_template(templatefile)
# Read in the named text file and expand ${var}
# inside the file
{
insert_lines:
"${templatefile}"
insert_type => "file",
comment => "Expand variables in the template file",
expand_scalars => "true";
}
##
bundle agent cronjob(commands,user,hours,mins)
# For adding lines to crontab for a user
# methods:
# "cron" usebundle => cronjob("/bin/ls","mark","*","5,10");
{
vars:
SuSE::
"crontab" string => "/var/spool/cron/tabs";
!SuSE::
"crontab" string => "/var/spool/cron/crontabs";
files:
"${crontab}/${user}"
comment => "A user's regular batch jobs are added to this file",
create => "true",
edit_line => append_if_no_line("${mins} ${hours} * * * ${commands}"),
perms => mo("644","${user}");
processes:
"cron"
comment => "Most crons need to be huped after file changes",
signals => { "hup" };
}
##
## editing bodies
##
body edit_field quoted_var(newval,method)
{
field_separator => "\"";
select_field => "2";
value_separator => " ";
field_value => "${newval}";
field_operation => "${method}";
extend_fields => "false";
allow_blank_fields => "true";
}
##
body edit_field col(split,col,newval,method)
{
field_separator => "${split}";
select_field => "${col}";
value_separator => ",";
field_value => "${newval}";
field_operation => "${method}";
extend_fields => "true";
allow_blank_fields => "true";
}
##
body replace_with value(x)
{
replace_value => "${x}";
occurrences => "all";
}
##
body select_region INI_section(x)
{
select_start => "\[${x}\]\s*";
select_end => "\[.*\]\s*";
}
##
## edit_defaults
##
body edit_defaults std_defs
{
empty_file_before_editing => "false";
edit_backup => "false";
max_file_size => "300000";
}
##
body edit_defaults empty
{
empty_file_before_editing => "true";
edit_backup => "false";
max_file_size => "300000";
}
##
## location
##
body location start
{
before_after => "before";
}
##
body location after(str)
{
before_after => "after";
select_line_matching => "${str}";
}
##
## replace_with
##
##
body replace_with comment(c)
{
replace_value => "${c} $(match.1)";
occurrences => "all";
}
##
body replace_with uncomment
{
replace_value => "$(match.1)";
occurrences => "all";
}
####################################################
## agent bodyparts
####################################################
##
## action
##
body action if_elapsed(x)
{
ifelapsed => "${x}";
expireafter => "${x}";
}
##
body action measure_performance(x)
{
measurement_class => "Detect changes in ${this.promiser}";
ifelapsed => "${x}";
expireafter => "${x}";
}
##
body action warn_only
{
action_policy => "warn";
ifelapsed => "60";
}
##
body action bg(elapsed,expire)
{
ifelapsed => "${elapsed}";
expireafter => "${expire}";
background => "true";
}
##
body action ifwin_bg
{
windows::
background => "true";
}
##
body action immediate
{
ifelapsed => "0";
}
##
body action policy(p)
{
action_policy => "${p}";
}
##
# Log a message to log=[/file|stdout]
body action log_repaired(log,message)
{
log_string => "${sys.date}, ${message}";
log_repaired => "${log}";
}
##
## contain
##
body contain silent
{
no_output => "true";
}
##
body contain in_dir(s)
{
chdir => "${s}";
}
##
body contain in_dir_shell(s)
{
chdir => "${s}";
useshell => "true";
}
##
body contain silent_in_dir(s)
{
chdir => "${s}";
no_output => "true";
}
##
body contain in_shell
{
useshell => "true";
}
##
body contain setuid(x)
{
exec_owner => "${x}";
useshell => "false";
}
##
body contain setuid_sh(x)
{
exec_owner => "${x}";
useshell => "true";
}
##
body contain setuidgid_sh(owner,group)
{
exec_owner => "${owner}";
exec_group => "${group}";
useshell => "true";
}
##
body contain jail(owner,root,dir)
{
exec_owner => "${owner}";
useshell => "true";
chdir => "${dir}";
chroot => "${root}";
}
##
## classes
##
body classes if_repaired(x)
{
promise_repaired => { "${x}" };
}
##
body classes if_else(yes,no)
{
promise_kept => { "${yes}" };
promise_repaired => { "${yes}" };
repair_failed => { "${no}" };
repair_denied => { "${no}" };
repair_timeout => { "${no}" };
}
##
body classes cf2_if_else(yes,no)
# meant to match cf2 semantics
{
promise_repaired => { "${yes}" };
repair_failed => { "${no}" };
repair_denied => { "${no}" };
repair_timeout => { "${no}" };
}
##
body classes if_notkept(x)
{
repair_failed => { "${x}" };
repair_denied => { "${x}" };
repair_timeout => { "${x}" };
}
##
body classes if_ok(x)
{
promise_repaired => { "${x}" };
promise_kept => { "${x}" };
}
##
## Persistent classes
##
body classes state_repaired(x)
{
promise_repaired => { "${x}" };
persist_time => "10";
}
##
body classes enumerate(x)
#
# This is used by commercial editions to count
# instances of jobs in a cluster
#
{
promise_repaired => { "mXC_${x}" };
promise_kept => { "mXC_${x}" };
persist_time => "15";
}
###################################################
# agent bundles
###################################################
##..................................................
## files promises
##..................................................
##
## copy_from
##
body copy_from secure_cp(from,server)
{
source => "${from}";
servers => { "${server}" };
compare => "digest";
encrypt => "true";
verify => "true";
}
##
body copy_from remote_cp(from,server)
{
servers => { "${server}" };
source => "${from}";
compare => "mtime";
}
##
body copy_from local_cp(from)
{
source => "${from}";
}
##
body copy_from perms_cp(from)
{
source => "${from}";
preserve => "true";
}
##
# Copy only if the file does not already exist, i.e. seed the placement
body copy_from seed_cp(from)
{
source => "${from}";
compare => "exists";
}
##
body copy_from sync_cp(from,server)
{
servers => { "${server}" };
source => "${from}";
purge => "true";
preserve => "true";
}
##
body copy_from no_backup_cp(from)
{
source => "${from}";
copy_backup => "false";
}
##
body copy_from no_backup_rcp(from,server)
{
servers => { "${server}" };
source => "${from}";
compare => "mtime";
copy_backup => "false";
}
##
## link_from
##
body link_from ln_s(x)
{
link_type => "symlink";
source => "${x}";
when_no_source => "force";
}
##
body link_from linkchildren(tofile)
{
source => "${tofile}";
link_type => "symlink";
when_no_source => "force";
link_children => "true";
when_linking_children => "if_no_such_file"; # "override_file";
}
##
## perms
##
body perms m(mode)
{
mode => "${mode}";
}
##
body perms mo(mode,user)
{
owners => { "${user}" };
mode => "${mode}";
}
##
body perms mog(mode,user,group)
{
owners => { "${user}" };
groups => { "${group}" };
mode => "${mode}";
}
##
body perms og(u,g)
{
owners => { "${u}" };
groups => { "${g}" };
}
##
body perms owner(user)
{
owners => { "${user}" };
}
##
## ACLS (extended Unix perms)
##
body acl access_generic(acl)
# default/inherited ACLs are left unchanged,
# applicable for both files and directory on all platforms
{
acl_method => "overwrite";
aces => { "@{acl}" };
}
##
body acl strict
# NOTE: May need to take ownership of file/dir
# to be sure no-one else is allowed access
{
acl_method => "overwrite";
windows::
aces => { "user:Administrator:rwx" };
!windows::
aces => { "user:root:rwx" };
}
##
## depth_search
##
body depth_search recurse(d)
{
depth => "${d}";
xdev => "true";
}
##
body depth_search recurse_ignore(d,list)
{
depth => "${d}";
exclude_dirs => { @{list} };
}
##
## delete
##
body delete tidy
{
dirlinks => "delete";
rmdirs => "true";
}
##
## rename
##
body rename disable
{
disable => "true";
}
##
body rename rotate(level)
{
rotate => "${level}";
}
##
body rename to(file)
{
newname => "${file}";
}
##
## file_select
##
body file_select name_age(name,days)
{
leaf_name => { "${name}" };
mtime => irange(0,ago(0,0,"${days}",0,0,0));
file_result => "mtime.leaf_name";
}
##
body file_select days_old(days)
{
mtime => irange(0,ago(0,0,"${days}",0,0,0));
file_result => "mtime";
}
##
body file_select size_range(from,to)
{
search_size => irange("${from}","${to}");
file_result => "size";
}
##
body file_select exclude(name)
{
leaf_name => { "${name}"};
file_result => "!leaf_name";
}
##
body file_select plain
{
file_types => { "plain" };
file_result => "file_types";
}
body file_select dirs
{
file_types => { "dir" };
file_result => "file_types";
}
##
body file_select by_name(names)
{
leaf_name => { @{names}};
file_result => "leaf_name";
}
##
body file_select ex_list(names)
{
leaf_name => { @{names}};
file_result => "!leaf_name";
}
##
## changes
##
body changes detect_all_change
# This is fierce, and will cost disk cycles
{
hash => "best";
report_changes => "all";
update_hashes => "yes";
}
##
body changes detect_content
# This is a cheaper alternative
{
hash => "md5";
report_changes => "content";
update_hashes => "yes";
}
##
body changes noupdate
# Use on (small) files that should never change
{
hash => "sha256";
report_changes => "content";
update_hashes => "no";
}
##
body changes diff
# Generates diff report (Nova and above)
{
hash => "sha256";
report_changes => "content";
report_diffs => "true";
update_hashes => "yes";
}
##--------------------------------------------------------------
## Packages promises
##--------------------------------------------------------------
body package_method zypper
{
package_changes => "bulk";
package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\"";
package_patch_list_command => "/usr/bin/zypper patches";
package_installed_regex => "i.*";
package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*";
package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_patch_installed_regex => ".*Installed.*|.*Not Applicable.*";
package_patch_name_regex => "[^|]+\|\s+([^\s]+).*";
package_patch_version_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*";
package_name_convention => "${name}";
package_add_command => "/usr/bin/zypper --non-interactive install";
package_delete_command => "/usr/bin/zypper --non-interactive remove --force-resolution";
package_update_command => "/usr/bin/zypper --non-interactive update";
package_patch_command => "/usr/bin/zypper --non-interactive patch$"; # $ means no args
package_verify_command => "/usr/bin/zypper --non-interactive verify$";
}
##
body package_method apt
{
package_changes => "bulk";
package_list_command => "/usr/bin/dpkg -l";
package_list_name_regex => "ii\s+([^\s]+).*";
package_list_version_regex => "ii\s+[^\s]+\s+([^\s]+).*";
package_installed_regex => ".*"; # all reported are installed
package_name_convention => "${name}";
package_list_update_ifelapsed => "240"; # 4 hours
have_aptitude::
package_add_command => "/usr/bin/aptitude --assume-yes install";
package_list_update_command => "/usr/bin/aptitude update";
package_delete_command => "/usr/bin/aptitude --assume-yes remove";
package_update_command => "/usr/bin/aptitude --assume-yes install";
package_verify_command => "/usr/bin/aptitude show";
package_noverify_regex => "(State: not installed|E: Unable to locate package .*)";
!have_aptitude::
package_add_command => "/usr/bin/apt-get --yes install";
package_list_update_command => "/usr/bin/apt-get update";
package_delete_command => "/usr/bin/apt-get --yes remove";
package_update_command => "/usr/bin/apt-get --yes install";
package_verify_command => "/usr/bin/dpkg -s";
package_noverify_returncode => "1";
}
##
body package_method rpm_version(repo)
{
package_changes => "individual";
package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version} | %{arch}\n\"";
package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s|]+).*";
package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s|]+).*";
package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_installed_regex => "i.*";
package_file_repositories => { "${repo}" };
package_name_convention => "${name}-${version}-${arch}.rpm";
package_add_command => "/bin/rpm -ivh ";
package_delete_command => "/bin/rpm -e --nodeps";
package_verify_command => "/bin/rpm -V";
package_update_command => "/bin/rpm -Uvh ";
package_noverify_regex => ".*[^\s].*";
}
##
body package_method msi_implicit(repo)
# Use whole file name as promiser, e.g. "7-Zip-4.50-x86_64.msi",
# the name, version and arch is then deduced from the promiser
{
package_changes => "individual";
package_file_repositories => { "${repo}" };
package_installed_regex => ".*";
package_name_convention => "${name}-${version}-${arch}.msi";
package_delete_convention => "${firstrepo}${name}-${version}-${arch}.msi";
package_name_regex => "^(\S+)-(\d+\.?)+";
package_version_regex => "^\S+-((\d+\.?)+)";
package_arch_regex => "^\S+-[\d\.]+-(.*).msi";
package_add_command => "\"${sys.winsysdir}\msiexec.exe\" /qn /i";
package_update_command => "\"${sys.winsysdir}\msiexec.exe\" /qn /i";
package_delete_command => "\"${sys.winsysdir}\msiexec.exe\" /qn /x";
}
##
body package_method msi_explicit(repo)
# use software name as promiser, e.g. "7-Zip", and explicitly
# specify any package_version and package_arch
{
package_changes => "individual";
package_file_repositories => { "${repo}" };
package_installed_regex => ".*";
package_name_convention => "${name}-${version}-${arch}.msi";
package_delete_convention => "${firstrepo}${name}-${version}-${arch}.msi";
package_add_command => "\"${sys.winsysdir}\msiexec.exe\" /qn /i";
package_update_command => "\"${sys.winsysdir}\msiexec.exe\" /qn /i";
package_delete_command => "\"${sys.winsysdir}\msiexec.exe\" /qn /x";
}
##
body package_method yum
{
package_changes => "bulk";
package_list_command => "/usr/bin/yum list installed";
package_patch_list_command => "/usr/bin/yum check-update";
# Remember to escape special characters like |
package_list_name_regex => "([^.]+).*";
package_list_version_regex => "[^\s]\s+([^\s]+).*";
package_list_arch_regex => "[^.]+\.([^\s]+).*";
package_installed_regex => ".*installed.*";
package_name_convention => "${name}.${arch}";
package_delete_convention => "${name}";
package_list_update_ifelapsed => "240";
package_patch_installed_regex => "";
package_patch_name_regex => "([^.]+).*";
package_patch_version_regex => "[^\s]\s+([^\s]+).*";
package_patch_arch_regex => "[^.]+\.([^\s]+).*";
package_add_command => "/usr/bin/yum -y install";
package_delete_command => "/bin/rpm -e";
package_verify_command => "/bin/rpm -V";
}
##
body package_method yum_rpm
# Contributed by Trond Hasle Amundsen
# More efficient package method for RedHat - uses rpm to list instead of yum
# Notes:
# - using ${name}.${arch} instead of ${name} for package_name_convention
# causes uninstallation to fail.
# - using allmatches to remove for all architectures
#
{
package_changes => "bulk";
package_list_command => "/bin/rpm -qa --qf '%{name} %{version}-%{release} %{arch}\n'";
package_patch_list_command => "/usr/bin/yum check-update";
package_list_name_regex => "^(\S+?)\s\S+?\s\S+$";
package_list_version_regex => "^\S+?\s(\S+?)\s\S+$";
package_list_arch_regex => "^\S+?\s\S+?\s(\S+)$";
package_installed_regex => ".*";
package_name_convention => "${name}";
package_patch_installed_regex => "";
package_patch_name_regex => "([^.]+).*";
package_patch_version_regex => "[^\s]\s+([^\s]+).*";
package_patch_arch_regex => "[^.]+\.([^\s]+).*";
package_add_command => "/usr/bin/yum -y install";
package_update_command => "/usr/bin/yum -y update";
package_delete_command => "/bin/rpm -e --allmatches";
package_verify_command => "/bin/rpm -V";
}
##
# The solaris package system is poorly designed, with too many different
# names to track. See the example in tests/units/unit_package_solaris.cf
# to see how to use this
body package_method solaris (pkgname, spoolfile, adminfile)
{
package_changes => "individual";
package_list_command => "/usr/bin/pkginfo -l";
package_multiline_start => "\s*PKGINST:\s+[^\s]+";
package_list_name_regex => "\s*PKGINST:\s+([^\s]+)";
package_list_version_regex => "\s*VERSION:\s+([^\s]+)";
package_list_arch_regex => "\s*ARCH:\s+([^\s]+)";
package_installed_regex => "\s*STATUS:\s*(completely|partially)\s+installed.*";
package_name_convention => "${name}";
package_add_command => "/usr/sbin/pkgadd -n -a /tmp/${adminfile} -d /tmp/${spoolfile}";
package_delete_command => "/usr/sbin/pkgrm -n -a /tmp/${adminfile}";
}
##
body package_method freebsd
{
package_changes => "individual";
# Could use rpm for this
package_list_command => "/usr/sbin/pkg_info";
# Remember to escape special characters like |
package_list_name_regex => "([^-]+).*";
package_list_version_regex => "[^-]+-([^\s]+).*";
package_name_regex => "([^-]+).*";
package_version_regex => "[^-]+-([^\s]+).*";
package_installed_regex => ".*";
package_name_convention => "${name}-${version}";
package_add_command => "/usr/sbin/pkg_add -r";
package_delete_command => "/usr/sbin/pkg_delete";
}
##
# Single bundle for all the similar managers simplifies promises
body package_method generic
{
SuSE::
package_changes => "bulk";
package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\"";
package_patch_list_command => "/usr/bin/zypper patches";
package_installed_regex => "i.*";
package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*";
package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_patch_installed_regex => ".*Installed.*|.*Not Applicable.*";
package_patch_name_regex => "[^|]+\|\s+([^\s]+).*";
package_patch_version_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*";
package_name_convention => "${name}";
package_add_command => "/usr/bin/zypper --non-interactive install";
package_delete_command => "/usr/bin/zypper --non-interactive remove --force-resolution";
package_update_command => "/usr/bin/zypper --non-interactive update";
package_patch_command => "/usr/bin/zypper --non-interactive patch$"; # $ means no args
package_verify_command => "/usr/bin/zypper --non-interactive verify$";
redhat::
package_changes => "bulk";
package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\"";
package_patch_list_command => "/usr/bin/yum check-update";
package_installed_regex => "i.*";
package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*";
package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_name_convention => "${name}";
package_list_update_ifelapsed => "240";
package_patch_installed_regex => "";
package_patch_name_regex => "([^.]+).*";
package_patch_version_regex => "[^\s]\s+([^\s]+).*";
package_patch_arch_regex => "[^.]+\.([^\s]+).*";
package_add_command => "/usr/bin/yum -y install";
package_delete_command => "/bin/rpm -e";
package_verify_command => "/bin/rpm -V";
debian::
package_changes => "bulk";
package_list_command => "/usr/bin/dpkg -l";
package_list_name_regex => "ii\s+([^\s]+).*";
package_list_version_regex => "ii\s+[^\s]+\s+([^\s]+).*";
package_installed_regex => ".*"; # all reported are installed
package_name_convention => "${name}";
package_list_update_ifelapsed => "240"; # 4 hours
debian.have_aptitude::
package_add_command => "/usr/bin/aptitude --assume-yes install";
package_list_update_command => "/usr/bin/aptitude update";
package_delete_command => "/usr/bin/aptitude --assume-yes remove";
package_update_command => "/usr/bin/aptitude --assume-yes install";
package_verify_command => "/usr/bin/aptitude show";
package_noverify_regex => "(State: not installed|E: Unable to locate package .*)";
debian.!have_aptitude::
package_add_command => "/usr/bin/apt-get --yes install";
package_list_update_command => "/usr/bin/apt-get update";
package_delete_command => "/usr/bin/apt-get --yes remove";
package_update_command => "/usr/bin/apt-get --yes install";
package_verify_command => "/usr/bin/dpkg -s";
package_noverify_returncode => "1";
freebsd::
package_changes => "individual";
package_list_command => "/usr/sbin/pkg_info";
package_list_name_regex => "([^-]+).*";
package_list_version_regex => "[^-]+-([^\s]+).*";
package_name_regex => "([^-]+).*";
package_version_regex => "[^-]+-([^\s]+).*";
package_installed_regex => ".*";
package_name_convention => "${name}-${version}";
package_add_command => "/usr/sbin/pkg_add -r";
package_delete_command => "/usr/sbin/pkg_delete";
}
##-------------------------------------------------------
## storage promises
##-------------------------------------------------------
body volume min_free_space(free)
{
check_foreign => "false";
freespace => "${free}";
sensible_size => "10000";
sensible_count => "2";
}
##
body mount nfs(server,source)
{
mount_type => "nfs";
mount_source => "${source}";
mount_server => "${server}";
edit_fstab => "true";
}
##
body mount nfs_p(server,source,perm)
{
mount_type => "nfs";
mount_source => "${source}";
mount_server => "${server}";
mount_options => {"${perm}"};
edit_fstab => "true";
}
##
body mount unmount
{
mount_type => "nfs";
edit_fstab => "true";
unmount => "true";
}
##-------------------------------------------------------
## process promises
##-------------------------------------------------------
body process_select exclude_procs(x)
{
command => "${x}";
process_result => "!command";
}
##
body process_count check_range(name,lower,upper)
{
match_range => irange("${lower}","${upper}");
out_of_range_define => { "${name}_out_of_range" };
}
##
## service promises
##
body service_method bootstart
{
service_autostart_policy => "boot_time";
service_dependence_chain => "start_parent_services";
windows::
service_type => "windows";
}
##
body service_method force_deps
{
service_dependence_chain => "all_related";
windows::
service_type => "windows";
}
####################################################
## monitor bodyparts
####################################################
body match_value scan_log(line)
{
select_line_matching => "${line}";
track_growing_file => "true";
}
##
body action sample_rate(x)
{
ifelapsed => "${x}";
expireafter => "10";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
# This our core-library of common
# function. That's our knowledge !
#
# Just bodies and editbundles here
#
############################################
body depth_search recurse_visible(d)
{
depth => "${d}";
exclude_dirs => { "\..*" };
}
#perms validation
body perms u_p(p)
{
mode => "${p}";
}
#########################################################
#server may be a list
body copy_from cp(from,server)
{
servers => { "${server}" };
source => "${from}";
compare => "digest";
community_edition::
portnumber => "5309";
}
body copy_from scp(from, server,trustkey,preserve,purge)
{
servers => { "${server}" };
source => "${from}";
compare => "digest";
encrypt => "true";
verify => "true";
trustkey => "${trustkey}";
preserve => "${preserve}"; #preserver permissions
purge => "${purge}";
community_edition::
portnumber => "5309";
}
# This is an evolved version of copy_from scp that uses local copies if we are
# running on a policy server instead of copying from a localhost remote blindly.
body copy_from rudder_copy_from(from, server,compare,trustkey,preserve,purge) {
source => "$(from)";
compare => "$(compare)";
encrypt => "true";
verify => "true";
trustkey => "${trustkey}";
preserve => "${preserve}"; # Preserve the permissions
purge => "${purge}";
copy_backup => "timestamp";
!root_server::
servers => { "${server}" };
community_edition::
portnumber => "5309";
}
body copy_from copy(from) {
source => "$(from)";
copy_backup => "false";
community_edition::
portnumber => "5309";
}
body copy_from copy(from)
{
source => "${from}";
copy_backup => "false";
preserve => "true";
}
body copy_from copy_digest(from)
{
source => "${from}";
copy_backup => "timestamp";
preserve => "true";
compare => "digest";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#
# Just bodies and editbundles here
#
############################################
#perms validation
body perms p(user,mode)
{
owners => { "${user}" };
mode => "${mode}";
}
############################################
body file_select cf3_files
{
leaf_name => { "cf-.*" };
file_result => "leaf_name";
}
#########################################################
body changes lay_trip_wire
{
hash => "best";
report_changes => "content";
update_hashes => "yes";
}
########################################################
body action longjob
{
ifelapsed => "240"; # run only every 4 hours
}
#######################################################
# For the library
#######################################################
body edit_defaults noempty_backup
{
empty_file_before_editing => "false";
edit_backup => "timestamp"; # we want to keep a track of everything
max_file_size => "1024000";
}
body edit_defaults empty_backup
{
empty_file_before_editing => "true";
edit_backup => "timestamp";
max_file_size => "1024000";
}
body edit_defaults def_no_backup
{
empty_file_before_editing => "false";
edit_backup => "false";
max_file_size => "1024000";
}
########################################################
########################################################
bundle edit_line DeleteLinesMatching(regex)
{
delete_lines:
"${regex}",
action => WarnOnly;
}
########################################################
body action WarnOnly
{
action_policy => "warn";
ifelapsed => "60";
}
########################################
# Bodies
########################################
body replace_with With(x)
{
replace_value => "${x}";
occurrences => "all";
}
########################################
################################
# For commands with a >
################################
body contain outputable
{
useshell => "true";
no_output=> "false";
}
################################
# Process is launched ?
################################
body process_count islaunched(class)
{
match_range => irange("1", "500");
in_range_define => { "${class}"};
out_of_range_define => {"no_${class}"};
}
###########################################################################################
# Persistent class
# If the promise is repaired, define repaired for length minutes and undefine failed
# If the promise is not kept, undefine repaired and define failed for length minutes
##########################################################################################
body classes persistant_class(repaired, failed, length)
{
promise_repaired => { "${repaired}" };
repair_failed => { "${failed}" };
repair_denied => { "${failed}" };
repair_timeout => { "${failed}" };
cancel_repaired => {"${failed}"};
cancel_notkept => {"${repaired}"};
persist_time => "${length}";
}
###########################################################################################
# Persistent class
# If the promise is repaired/kept, define repaired for length minutes and undefine failed
# If the promise is not kept, undefine repaired and define failed for length minutes
##########################################################################################
body classes set_persist_classes(repaired, failed, length)
{
promise_kept => { "${repaired}" };
promise_repaired => { "${repaired}" };
repair_failed => { "${failed}" };
repair_denied => { "${failed}" };
repair_timeout => { "${failed}" };
cancel_kept => {"${failed}"};
cancel_repaired => {"${failed}"};
cancel_notkept => {"${repaired}"};
persist_time => "${length}";
}
################################################
# kept_if_else
# set kept if the promise is kept
# yes if repaired
# no if cannot repair
################################################
body classes kept_if_else(kept, yes,no)
{
promise_kept => { "${kept}" };
promise_repaired => { "${yes}" };
repair_failed => { "${no}" };
repair_denied => { "${no}" };
repair_timeout => { "${no}" };
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#
# Define what an agent has to do when it updates
# its promises
#
#simple copy method
body copy_from remote(server, path)
{
servers => {
"${server}"
};
encrypt => "true";
trustkey => "true";
source => "${path}";
compare => "digest";
preserve => "true"; #preserver permissions
verify => "true";
purge => "false";
owners => {"root"};
community_edition::
portnumber => "5309";
}
bundle common server_info
{
vars:
any::
"cfserved" string => "%%POLICY_SERVER_HOSTNAME%%";
"policy_files" string => "/var/rudder/share/root"; #directory where to look for promises in the server for that client
}
bundle agent update
{
vars:
"client_inputs" string => "${sys.workdir}/inputs"; #where to put the files on the client when downloaded
nova_edition::
"server_inputs" string => "${server_info.policy_files}/rules/cfengine-nova"; #actual directory with promises
community_edition::
"server_inputs" string => "${server_info.policy_files}/rules/cfengine-community"; #actual directory with promises
files:
any::
"${g.rudder_ncf}/."
create => "true",
comment => "Make sure the ncf directory exists";
"${g.rudder_ncf}/common"
copy_from => remote("${server_info.cfserved}", "${g.rudder_ncf_origin_common}"),
depth_search => recurse("inf"),
action => immediate,
classes => success("rudder_ncf_common_updated", "rudder_ncf_common_update_error", "rudder_ncf_common_updated_ok"),
comment => "Update the common Rudder ncf instance";
"${g.rudder_ncf}/local"
copy_from => remote("${server_info.cfserved}", "${g.rudder_ncf_origin_local}"),
depth_search => recurse("inf"),
action => immediate,
classes => success("rudder_ncf_local_updated", "rudder_ncf_local_update_error", "rudder_ncf_local_updated_ok"),
comment => "Update the local Rudder ncf instance";
!root_server::
"${g.rudder_tools}"
copy_from => remote("${server_info.cfserved}", "${g.rudder_tools}"),
depth_search => recurse("inf"),
action => immediate,
classes => success("rudder_tools_updated_ok", "rudder_tools_update_error");
"${client_inputs}"
copy_from => remote("${server_info.cfserved}","${server_inputs}"),
depth_search => recurse("inf"),
action => immediate,
classes => success("config", "no_update");
processes:
config::
"cf-serverd" restart_class => "start_server";
config.!windows::
"cf-execd" restart_class => "start_exec";
commands:
start_exec.!windows::
"${sys.cf_execd}",
action => u_ifwin_bg,
classes => outcome("executor");
start_exec.cygwin::
"${sys.cf_execd}",
action => u_ifwin_bg,
classes => outcome("executor");
start_server::
"${sys.cf_serverd}",
action => u_ifwin_bg,
classes => outcome("server");
#########################################################
services:
config.windows::
"CfengineNovaExec"
service_policy => "start",
service_method => u_bootstart,
classes => outcome("executor"),
comment => "Start the executor windows service now and at boot time";
reports:
server_ok::
"@@HasPolicyServer@@Inform@@hasPolicyServer-root#@common-root##${g.uuid}@#Started the server - system ready to serve";
executor_ok::
"@@HasPolicyServer@@Inform@@hasPolicyServer-root#@common-root##${g.uuid}@#Started the scheduler - system functional";
no_update::
"@@HasPolicyServer@@Error@@hasPolicyServer-root#@common-root##${g.uuid}@#Cannot update policy files";
rudder_tools_update_error::
"@@HasPolicyServer@@Error@@hasPolicyServer-root#@common-root##${g.uuid}@#Cannot update Rudder tools";
rudder_ncf_common_update_error::
"@@HasPolicyServer@@Error@@hasPolicyServer-root#@common-root##${g.uuid}@#Cannot update Rudder common ncf instance";
rudder_ncf_local_update_error::
"@@HasPolicyServer@@Error@@hasPolicyServer-root#@common-root##${g.uuid}@#Cannot update Rudder local ncf instance";
}
############################################
body classes outcome(x)
{
promise_repaired => {"${x}_ok"};
}
############################################
body action u_background
{
background => "true";
}
############################################
body classes success(if, else)
{
promise_repaired => {"${if}"};
repair_failed => { "${else}" };
repair_denied => { "${else}" };
repair_timeout => { "${else}" };
}
############################################
body action u_ifwin_bg
{
windows::
background => "true";
}
body service_method u_bootstart
{
service_autostart_policy => "boot_time";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent process_matching
{
vars:
# This deliberately excludes cf-execd which is handled separately below
"cf_components" slist => { "cf-key",
"cf-monitord", "cf-promises",
"cf-runagent", "cf-serverd" };
windows::
"stop_signal" string => "kill";
!windows::
"stop_signal" string => "term";
classes:
"restart_cf" expression => "Hr05.Min00_05";
processes:
restart_cf.!policy_server::
"${cf_components}" signals => { "${stop_signal}" };
restart_cf.policy_server::
"${sys.workdir}/bin/${cf_components}" signals => { "${stop_signal}" };
restart_cf.!windows::
"${sys.workdir}/bin/cf-execd" signals => { "${stop_signal}" };
commands:
restart_cf.!windows::
"${sys.cf_serverd}";
"${sys.cf_execd}";
services:
restart_cf.windows::
"CfengineNovaExec"
service_policy => "stop",
comment => "Stop the executor service, part of scheduled restart";
"CfengineNovaExec"
service_policy => "start",
comment => "Start the executor service, part of scheduled restart";
reports:
restart_cf::
"Reloaded configuration of all Cfengine components";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#######################################################
#
# Server specific configuration
#
#######################################################
bundle server access_rules
{
access:
policy_server::
"root"
handle => "policy_server_uuid",
resource_type => "literal",
admit => {".*"};
"${def.dir_masterfiles}"
handle => "grant_access_policy",
comment => "Grant access to the policy updates",
maproot => { @{def.acl} },
admit => { @{def.acl} };
"${g.rudder_tools}"
maproot => { @{def.acl} },
admit => { @{def.acl} };
"${g.rudder_ncf_origin_common}"
maproot => { @{def.acl} },
admit => { @{def.acl} };
"${g.rudder_ncf_origin_local}"
maproot => { @{def.acl} },
admit => { @{def.acl} };
any::
# the policy server must have access to the cfengine folder
"${sys.workdir}"
maproot => { host2ip("%%POLICY_SERVER_HOSTNAME%%"), escape("%%POLICY_SERVER_HOSTNAME%%") },
admit => { host2ip("%%POLICY_SERVER_HOSTNAME%%"), escape("%%POLICY_SERVER_HOSTNAME%%") };
roles:
# Allow user root to set any class
".*" authorize => { "root" };
}
bundle common def
{
vars:
"policy_server" string => "%%POLICY_SERVER_HOSTNAME%%";
"dir_masterfiles" string => translatepath("${sys.workdir}/masterfiles");
# List here the IP masks that we grant access to on the server
policy_server::
"acl" slist => {
"%%POLICY_SERVER_ALLOWED_NETWORKS%%"
};
!policy_server::
"acl" slist => {
"${def.policy_server}"
};
}
body server control
{
trustkeysfrom => {
"127.0.0.0/8" , "::1",
@{def.acl} ,
host2ip("%%POLICY_SERVER_HOSTNAME%%"), "%%POLICY_SERVER_HOSTNAME%%"
}; #trustkey allows the exchange of keys
allowconnects => {
@{def.acl} ,
host2ip("%%POLICY_SERVER_HOSTNAME%%"), "%%POLICY_SERVER_HOSTNAME%%"
};
maxconnections => "1000";
logallconnections => "true";
cfruncommand => "${sys.workdir}/bin/cf-agent -f failsafe.cf && ${sys.workdir}/bin/cf-agent";
allowusers => { "root" };
skipverify => { "127.0.0.0/8" , "::1", @{def.acl} };
community_edition::
port => "5309";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent root_alive_check
{
vars:
"sites_to_check" slist => { "http://localhost:8080/rudder/api/status", "http://localhost:8080/endpoint/api/status" };
methods:
"any" usebundle => generic_alive_check("${sites_to_check}");
}
bundle agent generic_alive_check(site_to_check)
{
vars:
"sitename" string => canonify("${site_to_check}");
"cleanup_failed_classes" slist => { "site_down_once_${sitename}", "site_alivecheck_restart_jetty_${sitename}" };
"failed_result_class" string => "site_down_once_${sitename}",
ifvarclass => "!site_down_once_${sitename}.!first_iteration_passed";
"site_failure_persist_time" string => "10",
ifvarclass => "!site_down_once_${sitename}.!first_iteration_passed";
"failed_result_class" string => "site_alivecheck_restart_jetty_${sitename}",
ifvarclass => "site_down_once_${sitename}.!first_iteration_passed";
"site_failure_persist_time" string => "0",
ifvarclass => "site_down_once_${sitename}.!first_iteration_passed";
classes:
"first_iteration_passed" expression => "any";
methods:
"any" usebundle => generic_process_check_process(".*java.*/opt/rudder/jetty7/start.jar", "rudder-jetty", "true"),
ifvarclass => "site_alivecheck_restart_jetty_${sitename}",
classes => set_persist_classes("site_alivecheck_jetty_restarted_${sitename}", "site_down_once_${sitename}" ,"0");
commands:
"/usr/bin/curl -s ${site_to_check} |/bin/grep -q OK"
contain => in_shell_silent,
classes => set_persist_classes_alivecheck("site_ok", "${failed_result_class}", "@{generic_alive_check.cleanup_failed_classes}", "${site_failure_persist_time}"),
comment => "Checking if ${site_to_check} is alive";
reports:
cfengine::
"@@DistributePolicy@@result_success@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The ${site_to_check} web application is running"
ifvarclass => "site_ok.!site_down_once_${sitename}";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#This is the first time the ${site_to_check} web application failed to respond. Deferring the restart."
ifvarclass => "site_down_once_${sitename}.!site_alivecheck_restart_jetty_${sitename}";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The ${site_to_check} web application failed to respond for the second time. Restarting rudder-jetty NOW !"
ifvarclass => "site_alivecheck_restart_jetty_${sitename}";
}
body classes set_persist_classes_alivecheck(repaired, failed, cancelifok, length)
{
promise_kept => { "${repaired}" };
promise_repaired => { "${repaired}" };
repair_failed => { "${failed}" };
repair_denied => { "${failed}" };
repair_timeout => { "${failed}" };
cancel_kept => {"@{cancelifok}"};
cancel_repaired => {"@{cancelifok}"};
cancel_notkept => {"${repaired}"};
persist_time => "${length}";
}
#####################################################################################
# Copyright 2011-2014 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent root_logrotate_check
{
vars:
(debian_5|debian_6).!ubuntu::
"logrotate_file" string => "${sys.workdir}/inputs/distributePolicy/logrotate.conf/rudder.old-debian";
debian.!(debian_5|debian_6).!ubuntu::
"logrotate_file" string => "${sys.workdir}/inputs/distributePolicy/logrotate.conf/rudder.debian";
ubuntu::
"logrotate_file" string => "${sys.workdir}/inputs/distributePolicy/logrotate.conf/rudder.ubuntu";
redhat::
"logrotate_file" string => "${sys.workdir}/inputs/distributePolicy/logrotate.conf/rudder.rhel";
!debian.!ubuntu.!redhat::
"logrotate_file" string => "${sys.workdir}/inputs/distributePolicy/logrotate.conf/rudder.suse";
files:
"/etc/logrotate.d/rudder"
copy_from => copy_digest("${logrotate_file}"),
classes => kept_if_else("rudder_logrotate_conf_ok", "rudder_logrotate_conf_copied", "cannot_copy_rudder_logrotate_conf"),
comment => "Copying the logrotate configuration";
reports:
cfengine::
"@@DistributePolicy@@result_success@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The logrotate configuration is correct"
ifvarclass => "rudder_logrotate_conf_ok.!rudder_logrotate_conf_copied.!cannot_copy_rudder_logrotate_conf";
"@@DistributePolicy@@result_repaired@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The logrotate configuration has been updated"
ifvarclass => "rudder_logrotate_conf_copied.!cannot_copy_rudder_logrotate_conf";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The logrotate configuration could not be updated"
ifvarclass => "cannot_copy_rudder_logrotate_conf";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent root_postgres_check
{
vars:
SuSE::
"configuration_statements" slist => { "host all rudder ::1/128 md5", "host all rudder 127.0.0.1/32 md5" };
files:
SuSE::
"/var/lib/pgsql/data/pg_hba.conf"
edit_line => prepend("${configuration_statements}"),
edit_defaults => noempty_backup,
classes => kept_if_else("psql_conf_ok", "psql_conf_updated", "psql_conf_update_error"),
comment => "Edit the SuSE postgresql configuration to enable account-less logins";
commands:
SuSE::
"/etc/init.d/postgresql"
args => "restart",
classes => kept_if_else("psql_restart_ok", "psql_restart_ok", "psql_restart_error"),
ifvarclass => "psql_conf_updated";
reports:
SuSE::
# Report about the configuration file edition
"@@DistributePolicy@@result_success@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The SuSE specific postgresql configuration is present"
ifvarclass => "psql_conf_ok.!psql_conf_updated.!psql_conf_update_error";
"@@DistributePolicy@@result_repaired@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The SuSE specific postgresql configuration has been added"
ifvarclass => "psql_conf_updated.!psql_conf_update_error";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The SuSE specific postgresql configuration could not be added"
ifvarclass => "psql_conf_update_error";
# Reports about Postgres restart status
"@@DistributePolicy@@log_info@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#PostgreSQL has been restarted"
ifvarclass => "psql_restart_ok";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#PostgreSQL restart has failed! Rudder is most certainly broken..."
ifvarclass => "psql_restart_error";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent root_integrity_check
{
files:
"${g.rudder_var}/configuration-repository"
create => "true",
action => WarnOnly,
classes => if_else("rudder_integrity_ok", "rudder_integrity_failed");
reports:
cfengine::
"@@DistributePolicy@@result_success@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The ${g.rudder_var}/configuration-repository directory is present"
ifvarclass => "rudder_integrity_ok.!rudder_integrity_failed";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#EMERGENCY: THE ${g.rudder_var}/configuration-repository DIRECTORY IS *ABSENT*. THIS ORCHESTRATOR WILL *NOT* OPERATE CORRECTLY."
ifvarclass => "!rudder_integrity_ok|rudder_integrity_failed";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
# Configure rsyslog on the orchestrator
# This will provide promises to add the backports repos to Debian Lenny:
# - in sources.list
# - default apt_preferences to upgrade packages installed from backports
# - a package_method to install packages from backports via cfengine
bundle agent setup_debian_backports
{
vars:
"apt_source_line" slist => { "deb http://backports.debian.org/debian-backports lenny-backports" };
"apt_components" slist => { "main" };
files:
debian_5::
"/etc/apt/sources.list"
comment => "Include extra apt repos",
edit_line => append_if_no_lines("${apt_source_line} ${apt_components}"),
edit_defaults => noempty_backup,
classes => if_repaired("apt_sources_updated");
"/etc/apt/preferences"
comment => "Set automatic upgrades for packages installed from backports (recommended setting from backports.debian.org)",
create => "true",
edit_line => append_if_no_lines("Package: *${const.n}Pin: release a=lenny-backports${const.n}Pin-Priority: 200"),
edit_defaults => noempty_backup,
classes => if_repaired("apt_preferences_repaired");
commands:
apt_sources_updated::
"/usr/bin/aptitude"
args => "update";
reports:
apt_sources_updated::
"apt's sources.list was edited, and an aptitude update will now run";
apt_preferences_repaired::
"apt's /etc/apt/preferences file was changed";
}
bundle agent install_rsyslogd
{
vars:
# This will only read the first line if several match
"rsyslog_port_defined" int => getfields("rudder.syslog.port\s*=\s*[0-9]+\s*","/opt/rudder/etc/rudder-web.properties","=","rsyslog_port");
# Use standard rsyslog port number by default if not set in rudder-web.properties
rsyslog_port_not_found::
"rsyslog_port[2]" string => "514";
classes:
# There is no "equals" function for ints in CFEngine (currently, at least) so we compare strings
"rsyslog_port_not_found" expression => strcmp("${rsyslog_port_defined}","0");
"rsyslog_port_too_many" expression => isgreaterthan("${rsyslog_port_defined}","1");
files:
policy_server::
"/etc/rsyslog.d/rudder.conf"
create => "true",
edit_line => expand_template("${sys.workdir}/inputs/distributePolicy/rsyslog.conf/rudder.conf"),
edit_defaults => empty_backup,
classes => cf2_if_else("rudder_rsyslog_conf_copied", "cannot_copy_rudder_rsyslog_conf"),
comment => "Copying rsyslog conf";
"/etc/rsyslog.conf"
edit_line => append_if_no_lines("$IncludeConfig /etc/rsyslog.d/*.conf"),
edit_defaults => noempty_backup,
comment => "Add the rsyslog.conf.d include if not already present",
classes => cf2_if_else("rsyslog_inc_ok" , "rsyslog_inc_failed");
policy_server.!SuSE::
"/etc/rsyslog.d/pgsql.conf"
edit_line => comment_all(),
edit_defaults => noempty_backup,
classes => cf2_if_else("rudder_rsyslog_pgsql", "cannot_update_rudder_rsyslog_pgsql"),
comment => "Removing the logging of all in the database";
packages:
policy_server.debian_5.!SuSE::
"rsyslog"
package_policy => "add",
package_method => debian_backports,
classes => cf2_if_else("rsyslog_installed", "cant_install_rsyslog"),
comment => "Installing rsyslog using apt backports";
"rsyslog-pgsql"
package_policy => "add",
package_method => debian_backports,
classes => cf2_if_else("rsyslog_pgsql_installed", "cant_install_rsyslog_pgsql"),
comment => "Installing rsyslog_pgsql using apt backports";
policy_server.!debian_5.!SuSE::
"rsyslog"
package_policy => "add",
package_method => generic,
classes => cf2_if_else("rsyslog_installed", "cant_install_rsyslog"),
comment => "Installing rsyslog using apt backports";
"rsyslog-pgsql"
package_policy => "add",
package_method => generic,
classes => cf2_if_else("rsyslog_pgsql_installed", "cant_install_rsyslog_pgsql"),
comment => "Installing rsyslog_pgsql using apt backports";
commands:
policy_server.(rsyslog_installed|rsyslog_pgsql_installed|rudder_rsyslog_conf_copied|rudder_rsyslog_pgsql).!SuSE::
"/etc/init.d/rsyslog"
args => "restart",
classes => cf2_if_else("rsyslog_restarted", "cant_restart_rsyslog"),
comment => "restarting rsyslog";
policy_server.(rsyslog_installed|rsyslog_pgsql_installed|rudder_rsyslog_conf_copied|rudder_rsyslog_pgsql).SuSE::
"/etc/init.d/syslog"
args => "restart",
classes => cf2_if_else("rsyslog_restarted", "cant_restart_rsyslog"),
comment => "restarting rsyslog";
reports:
cant_install_rsyslog|cant_install_rsyslog_pgsql::
"Fatal : Can't install rsyslog or rsyslog_pgsql on the Rudder root server !";
cannot_copy_rudder_rsyslog_conf::
"Fatal : Can't copy the rsyslog configuration !";
rsyslog_inc_failed::
"Fatal : Can't enable the rsyslog include directory !";
cant_restart_rsyslog::
"Fatal : Can't restart rsyslog !";
cannot_update_rudder_rsyslog_pgsql::
"Fatal : Cannot update the pgsql configuration !";
rsyslog_restarted::
"Info : Restarted rsyslog";
rsyslog_port_not_found::
"Error: rsyslog port number is not set in /opt/rudder/etc/rudder-web.properties";
rsyslog_port_too_many::
"Warning: rsyslog port number has been set several times in /opt/rudder/etc/rudder-web.properties";
}
# Package method to install packages from debian-backports
body package_method debian_backports
{
debian::
package_changes => "bulk";
package_list_command => "/usr/bin/dpkg -l";
package_list_name_regex => "ii\s+([^\s]+).*";
package_list_version_regex => "ii\s+[^\s]+\s+([^\s]+).*";
package_installed_regex => ".*"; # all reported are installed
package_name_convention => "${name}";
package_list_update_ifelapsed => "240"; # 4 hours
debian.have_aptitude::
package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o Aptitude::Delete-Unused=false -t lenny-backports --assume-yes install";
package_list_update_command => "/usr/bin/aptitude update";
package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o Aptitude::Delete-Unused=false --assume-yes -q remove";
package_update_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o Aptitude::Delete-Unused=false --assume-yes install";
package_verify_command => "/usr/bin/aptitude show";
package_noverify_regex => "(State: not installed|E: Unable to locate package .*)";
debian.!have_aptitude::
package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o APT::Get::AutomaticRemove=false --yes -t lenny-backports install";
package_list_update_command => "/usr/bin/apt-get update";
package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o APT::Get::AutomaticRemove=false --yes -q remove";
package_update_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o APT::Get::AutomaticRemove=false --yes install";
package_verify_command => "/usr/bin/dpkg -s";
package_noverify_returncode => "1";
}
bundle edit_line comment_all()
{
replace_patterns:
# comment all lines
"^[^#](.*)"
replace_with => comments;
}
body replace_with comments
{
replace_value => "#${match.1}"; # backreference 0
occurrences => "all"; # first, last all
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent root_init_check()
{
vars:
"service[1][binary]" string => "/opt/rudder/libexec/slapd";
"service[1][initscript]" string => "rudder-slapd";
"service[2][binary]" string => ".*java.*/opt/rudder/jetty7/start.jar";
"service[2][initscript]" string => "rudder-jetty";
"service[3][binary]" string => "postgres: writer process";
"service[3][initscript]" string => "postgresql";
"service[5][binary]" string => "apache2";
"service[5][initscript]" string => "apache2";
"index" slist => getindices("service");
methods:
"any" usebundle => generic_process_check_process("${service[${index}][binary]}", "${service[${index}][initscript]}", "false");
"any" usebundle => generic_process_check_bootstart("${service[${index}][binary]}", "${service[${index}][initscript]}");
}
bundle agent generic_process_check_process(binary, initscript, force_restart)
{
vars:
"canoname" string => canonify("${binary}");
classes:
"forced_trigger_${canoname}" expression => strcmp("${force_restart}", "true");
processes:
# check the service status
"${binary}"
comment => "Check the process status",
restart_class => "process_restart_${canoname}",
classes => kept_if_else("service_running_${canoname}", "service_anomaly_${canoname}", "service_error_${canoname}");
commands:
"/etc/init.d/${initscript}"
args => "restart </dev/null >/dev/null 2>/dev/null",
contain => in_shell_silent,
# action => bg("0", "120"),
classes => kept_if_else("process_restart_ok_${canoname}", "process_restart_ok_${canoname}", "process_restart_error_${canoname}"),
ifvarclass => "process_restart_${canoname}|forced_trigger_${canoname}";
reports:
cfengine::
"@@DistributePolicy@@result_success@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The ${initscript} process is already running"
ifvarclass => "!process_restart_${canoname}.!forced_trigger_${canoname}";
"@@DistributePolicy@@result_repaired@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The ${initscript} process was not running and has been restarted"
ifvarclass => "process_restart_${canoname}.process_restart_ok_${canoname}.!forced_trigger_${canoname}";
"@@DistributePolicy@@result_repaired@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The ${initscript} process has been restarted"
ifvarclass => "process_restart_ok_${canoname}.forced_trigger_${canoname}";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The ${initscript} process couldn't be restarted"
ifvarclass => "process_restart_error_${canoname}";
}
bundle agent generic_process_check_bootstart(binary, initscript)
{
vars:
"canoname" string => canonify("${binary}");
files:
debian::
"/etc/rc2.d/S.*${initscript}.*"
create => "true",
action => WarnOnly,
classes => if_else("service_bootstarted_${canoname}", "service_unbootstarted_${canoname}");
commands:
(SuSE|redhat)::
"/sbin/chkconfig"
args => "--check ${initscript}",
classes => if_else("service_bootstarted_${canoname}", "service_unbootstarted_${canoname}"),
comment => "Check if the service ${initscript} is started on boot";
"/sbin/insserv"
args => "-d ${initscript}",
classes => if_else("service_bootstarted_ok_${canoname}", "service_bootstarted_fail_${canoname}"),
ifvarclass => "service_unbootstarted_${canoname}",
comment => "Set the service ${initscript} to start on boot";
debian::
"/usr/sbin/update-rc.d ${initscript} remove && /usr/sbin/update-rc.d ${initscript} defaults"
contain => in_shell,
classes => if_else("service_bootstarted_ok_${canoname}", "service_bootstarted_fail_${canoname}"),
ifvarclass => "service_unbootstarted_${canoname}",
comment => "Set the service ${initscript} to start on boot";
reports:
cfengine::
"@@DistributePolicy@@result_success@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#${initscript} is started on boot as required"
ifvarclass => "service_bootstarted_${canoname}";
"@@DistributePolicy@@result_repaired@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#${initscript} has been set to start on boot"
ifvarclass => "!service_bootstarted_${canoname}.service_bootstarted_ok_${canoname}";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#Could not set ${initscript} to start on boot!"
ifvarclass => "!service_bootstarted_${canoname}.service_bootstarted_fail_${canoname}";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent root_technique_reload
{
vars:
"root_technique_reload_rest_url" string => "http://localhost:8080/rudder/api/techniqueLibrary/reload";
classes:
"root_technique_reload_trigger" expression => fileexists("${g.rudder_base}/etc/force_technique_reload");
files:
root_technique_reload_rest_call_repaired::
"${g.rudder_base}/etc/force_technique_reload"
delete => tidy,
comment => "Deleting the force_technique_reload file because it is no longer relevant";
commands:
root_technique_reload_trigger::
"/usr/bin/curl -s ${root_technique_reload_rest_url} |/bin/grep -q OK"
contain => in_shell_silent,
classes => rudder_common_classes("root_technique_reload_rest_call"),
comment => "Reload the Technique library using the Rudder API";
reports:
root_technique_reload_trigger::
"@@DistributePolicy@@log_info@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The ${g.rudder_base}/etc/force_technique_reload file is present. Reloading Technique library...";
root_technique_reload_rest_call_repaired::
"@@DistributePolicy@@log_repaired@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Technique library has been reloaded.";
root_technique_reload_rest_call_failed::
"@@DistributePolicy@@log_warn@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Technique library failed to reload. Will try again next time";
}
#####################################################################################
# Copyright 2012 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle common p
{
vars:
"no" int => getfields("RUDDER_PSQL_PASSWORD:.*","/opt/rudder/etc/rudder-passwords.conf",":","psql_password");
"no2" int => getfields("RUDDER_OPENLDAP_BIND_PASSWORD:.*","/opt/rudder/etc/rudder-passwords.conf",":","ldap_password");
"properties_files" slist => { "${g.rudder_base}/etc/rudder-web.properties", "${g.rudder_base}/etc/inventory-web.properties" };
"managed_files" slist => { "@{properties_files}", "/root/.pgpass", "${g.rudder_base}/etc/openldap/slapd.conf" };
}
bundle agent root_password_check_disclaimer
{
vars:
"disclaim" slist => { "@{p.managed_files}" };
files:
"${disclaim}"
edit_line => insert_rudder_disclaimer,
comment => "Insert a disclaimer into Rudder";
}
bundle agent root_password_check_file
{
vars:
"pgpass[1]" string => "localhost";
"pgpass[2]" string => "5432";
"pgpass[3]" string => "rudder";
"pgpass[4]" string => "rudder";
"pgpass[5]" string => "${p.psql_password[2]}";
files:
"${g.rudder_base}/etc/rudder-passwords.conf"
perms => mog("600", "root", "root"),
classes => kept_if_else("file_ok", "file_repaired", "file_error");
"/root/.pgpass"
create => "true",
edit_line => root_password_check_file_pgpass("root_password_check_file.pgpass");
reports:
cfengine::
"@@DistributePolicy@@result_success@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Rudder passwords file is present and secure"
ifvarclass => "file_ok.!file_repaired.!file_error";
"@@DistributePolicy@@result_repaired@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Rudder passwords file permissions were fixed"
ifvarclass => "file_repaired.!file_error";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#EMERGENCY: THE ${g.rudder_base}/etc/rudder-passwords.conf FILE IS *ABSENT*. THIS RUDDER SERVER WILL *NOT* OPERATE CORRECTLY."
ifvarclass => "file_error";
}
bundle agent root_password_check_ldap
{
vars:
# Build an array using ldap configuration values
"rudder[ldap.authpw]" string => "${p.ldap_password[2]}";
"slapd[rootpw]" string => "${p.ldap_password[2]}"; # Looks like a bug, I can not use execresult("/opt/rudder/sbin/slappasswd -s ${p.ldap_password[2]}","noshell");
"prop_edit" slist => { "@{p.properties_files}" };
files:
"${prop_edit}"
edit_line => set_variable_values("root_password_check_ldap.rudder"),
classes => kept_if_else("rudder_web_password_integrity_ok", "rudder_web_password_integrity_changed", "rudder_web_password_integrity_failed"),
comment => "Verifying the Rudder Webapp properties file passwords and users";
"${g.rudder_base}/etc/openldap/slapd.conf"
edit_line => update_slapd("root_password_check_ldap.slapd"),
classes => kept_if_else("rudder_ldap_password_integrity_ok", "rudder_ldap_password_integrity_changed", "rudder_ldap_password_integrity_failed"),
comment => "Verifying the Rudder LDAP file password and user";
commands:
rudder_ldap_password_integrity_changed::
"/etc/init.d/rudder-slapd restart"
contain => in_shell,
classes => if_else("slapd_restarted", "slapd_restart_failed");
reports:
cfengine::
"@@DistributePolicy@@result_success@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Rudder Webapp configuration files are OK (checked LDAP password)"
ifvarclass => "rudder_web_password_integrity_ok.!rudder_web_password_integrity_changed.!rudder_web_password_integrity_failed";
"@@DistributePolicy@@result_repaired@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Rudder Webapp configuration files were updated with a new LDAP password"
ifvarclass => "rudder_web_password_integrity_changed.!rudder_web_password_integrity_failed";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Rudder Webapp configuration files could not be updated to set the LDAP password"
ifvarclass => "rudder_web_password_integrity_failed";
"@@DistributePolicy@@result_success@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The OpenLDAP configuration file is OK (checked rootdn password)"
ifvarclass => "rudder_ldap_password_integrity_ok.!rudder_ldap_password_integrity_changed.!rudder_ldap_password_integrity_failed";
"@@DistributePolicy@@result_repaired@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The OpenLDAP configuration file was updated with a new rootdn password"
ifvarclass => "rudder_ldap_password_integrity_changed.!rudder_ldap_password_integrity_failed";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The OpenLDAP configuration file could not be updated to set the rootdn password"
ifvarclass => "rudder_ldap_password_integrity_failed";
"@@DistributePolicy@@log_info@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#rudder-slapd has been restarted"
ifvarclass => "slapd_restarted";
}
bundle agent root_password_check_psql
{
vars:
"no" int => getfields("RUDDER_PSQL_PASSWORD:.*","/opt/rudder/etc/rudder-passwords.conf",":","psql_pass");
# Build an array using PSQL configuration values
"rudder[rudder.jdbc.password]" string => "${p.psql_password[2]}";
classes:
"psql_cant_connect" not => returnszero("/usr/bin/psql --host localhost --username rudder --dbname rudder --quiet --output /dev/null --command 'select 1'","noshell");
files:
"${g.rudder_base}/etc/rudder-web.properties"
edit_line => set_variable_values("root_password_check_psql.rudder"),
classes => kept_if_else("rudder_web_password_integrity_ok", "rudder_web_password_integrity_changed", "rudder_web_password_integrity_failed"),
comment => "Verifying the Rudder Webapp properties file passwords and users";
commands:
psql_cant_connect::
"/usr/bin/psql -q -c \"ALTER USER rudder WITH PASSWORD '${p.psql_password[2]}'\""
contain => setuid_sh("postgres"),
classes => if_else("postgres_updated", "postgres_update_failed");
reports:
cfengine::
"@@DistributePolicy@@result_success@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Rudder Webapp configuration files are OK (checked SQL password)"
ifvarclass => "rudder_web_password_integrity_ok.!rudder_web_password_integrity_changed.!rudder_web_password_integrity_failed";
"@@DistributePolicy@@result_repaired@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Rudder Webapp configuration files were updated with a new SQL password"
ifvarclass => "rudder_web_password_integrity_changed.!rudder_web_password_integrity_failed";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Rudder Webapp configuration files could not be updated to set the SQL password"
ifvarclass => "rudder_web_password_integrity_failed";
"@@DistributePolicy@@result_success@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Rudder PostgreSQL user account's password is correct and works"
ifvarclass => "!psql_cant_connect";
"@@DistributePolicy@@result_repaired@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Rudder PostgreSQL user account's password has been changed"
ifvarclass => "postgres_updated";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Rudder PostgreSQL user account's password could not be changed!"
ifvarclass => "postgres_update_failed";
}
bundle agent root_password_restart_jetty
{
commands:
rudder_web_password_integrity_changed::
"/etc/init.d/rudder-jetty restart </dev/null >/dev/null 2>/dev/null"
contain => in_shell,
classes => if_else("jetty_restarted", "jetty_restart_failed");
reports:
"@@DistributePolicy@@log_info@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#Jetty has been restarted"
ifvarclass => "jetty_restarted";
}
bundle agent root_password_check_dav
{
vars:
debian::
"webdav_check_wwwgroup" string => "www-data";
!debian::
"webdav_check_wwwgroup" string => "www";
SuSE::
"htpasswd_bin" string => "/usr/bin/htpasswd2";
!SuSE::
"htpasswd_bin" string => "/usr/bin/htpasswd";
classes:
"dav_cant_connect" not => returnszero("/usr/bin/curl -f -u ${g.davuser}:${g.davpw} -T /etc/motd http://localhost/inventory-updates/motd","noshell");
files:
"${g.rudder_base}/etc/htpasswd-webdav"
create => "true",
perms => mog("640", "root", "${webdav_check_wwwgroup}");
commands:
dav_cant_connect::
# Apache reads this file when it's changed, no need to restart or reload it after it's changed
"${htpasswd_bin}"
args => "-b ${g.rudder_base}/etc/htpasswd-webdav ${g.davuser} ${g.davpw}",
classes => kept_if_else("rudder_apache_davpassword_ok", "rudder_apache_davpassword_changed", "rudder_apache_davpassword_failed"),
comment => "Repairing the Rudder WebDAV user and password";
reports:
cfengine::
"@@DistributePolicy@@result_success@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Rudder WebDAV user and password are OK"
ifvarclass => "!dav_cant_connect";
"@@DistributePolicy@@result_repaired@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Rudder WebDAV user and password were updated"
ifvarclass => "rudder_apache_davpassword_changed.!rudder_apache_davpassword_failed";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Rudder WebDAV user and password could not be updated"
ifvarclass => "rudder_apache_davpassword_failed";
}
bundle edit_line update_slapd(tab)
{
vars:
"index" slist => getindices("${tab}");
delete_lines:
"${index}.*";
insert_lines:
"${index} ${${tab}[${index}]}" location => after("^rootdn.*");
}
bundle edit_line root_password_check_file_pgpass(parameter)
{
vars:
"indices" slist => getindices(${parameter});
field_edits:
"localhost:5432:rudder:.*"
# Set field of the file to parameter
edit_field => col(":","${indices}","${${parameter}[${indices}]}","set");
insert_lines:
"localhost:5432:rudder:${${parameter}[4]}:${${parameter}[5]}";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#
# Fetch the promises from the server to be available for others machines
# Must not do it on the RootServer though...
bundle agent propagatePromises
{
vars:
"server_data" string => "${server_info.policy_files}/share"; #actual directory with data to propagate
"client_data" string => "${g.rudder_var}/share/"; #where to put the files on the client when downloaded
files:
root_server::
"${g.rudder_tools}"
copy_from => copy("${g.rudder_base}/share/tools"),
depth_search => recurse_visible("inf"),
comment => "Fetching the tools for the promises execution",
classes => if_else("tools_propagated", "could_not_propagate_tools");
!root_server::
"${client_data}" #that's a loop on each files in client_inputs
copy_from => remote("${server_info.cfserved}","${server_data}"),
depth_search => recurse_visible("inf"),
comment => "Fetching the promises to propagate",
classes => if_else("promises_propagated", "could_not_propagate_promise");
"${g.rudder_tools}"
copy_from => remote("${server_info.cfserved}","${g.rudder_tools}"),
depth_search => recurse_visible("inf"),
comment => "Fetching the tools for the promises execution",
classes => if_else("tools_propagated", "could_not_propagate_tools");
"${sys.workdir}/masterfiles"
copy_from => remote("${server_info.cfserved}","${sys.workdir}/masterfiles"),
depth_search => recurse_visible("inf"),
file_select => no_license_dat, #We don't want to propagate a wrong license.dat
comment => "Fetching the bootstrap promises",
classes => if_else("masterfiles_propagated", "could_not_propagate_masterfiles");
"${sys.workdir}/masterfiles/license.dat"
copy_from => local_cp("${sys.workdir}/inputs/license.dat"),
comment => "Putting the right license in the bootstrap",
classes => if_else("license_copied", "could_not_copy_license");
reports:
could_not_propagate_promise::
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@propagatePromises@@None@@${g.execRun}##${g.uuid}@#Cannot propagate policy files";
could_not_propagate_tools::
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@propagatePromises@@None@@${g.execRun}##${g.uuid}@#Cannot propagate tools";
could_not_propagate_masterfiles::
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@propagatePromises@@None@@${g.execRun}##${g.uuid}@#Cannot propagate masterfiles";
could_not_copy_license::
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@propagatePromises@@None@@${g.execRun}##${g.uuid}@#Cannot copy local license";
}
# Sending the inventory to cmdb (or syncing with the server if we are a simple relay)
bundle agent sendInventoryToCmdb
{
files:
root_server::
"${g.rudder_inventories}/incoming"
transformer => "${g.rudder_tools}/send-clean.sh http://localhost:8080/endpoint/upload/ ${this.promiser} ${g.rudder_inventories}/received/ ${g.rudder_inventories}/failed/",
depth_search => recurse_visible(1),
file_select => all_files,
classes => if_else("inventory_sent", "rudder_send_inventory_to_cmdb_cant_send_inventory"),
comment => "Sending the inventory to the cmdb";
"${g.rudder_inventories}/accepted-nodes-updates"
transformer => "${g.rudder_tools}/send-clean.sh http://localhost:8080/endpoint/upload/ ${this.promiser} ${g.rudder_inventories}/received/ ${g.rudder_inventories}/failed/",
depth_search => recurse_visible(1),
file_select => all_files,
classes => if_else("inventory_sent", "rudder_send_inventory_to_cmdb_cant_send_inventory"),
comment => "Sending the inventory to the cmdb";
# NEED TO DO THE RSYNC PART
reports:
inventory_sent.!rudder_send_inventory_to_cmdb_cant_send_inventory::
"@@DistributePolicy@@result_success@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#Incoming inventories were successfully added to Rudder";
rudder_send_inventory_to_cmdb_cant_send_inventory::
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#Some inventories failed to add successfully to Rudder";
}
body file_select all_files
{
leaf_name => { ".*\..*" };
file_result => "leaf_name";
}
body file_select no_license_dat
{
leaf_name => { "license\.dat" };
file_result => "!leaf_name";
}
#####################################################################################
# Copyright 2012-2013 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent root_networks_check
{
vars:
"networks" string => join("${const.n}Allow from ","def.acl");
"file_path" string => "/opt/rudder/etc/rudder-networks.conf";
redhat::
"apache_init" string => "httpd";
!redhat::
"apache_init" string => "apache2";
files:
"${file_path}"
create => "true",
perms => mog("644", "root", "root"),
edit_defaults => empty_backup,
edit_line => insert_lines("Allow from 127.0.0.0/8${const.n}Allow from ${networks}"),
classes => kept_if_else("rudder_networks_ok", "rudder_networks_repaired","rudder_networks_failed"),
comment => "Copying rudder apache configuration";
commands:
rudder_networks_repaired::
"/etc/init.d/${apache_init}"
args => "reload",
classes => if_else("apache_restarted", "apache_restart_failed");
reports:
cfengine::
"@@DistributePolicy@@result_success@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The ${file_path} apache configuration file is OK"
ifvarclass => "rudder_networks_ok.!rudder_networks_repaired.!rudder_networks_failed";
"@@DistributePolicy@@result_repaired@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The ${file_path} apache configuration file has been corrected"
ifvarclass => "rudder_networks_repaired.!rudder_networks_failed";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The ${file_path} apache configuration file was NOT edited because of an error"
ifvarclass => "rudder_networks_failed";
"@@DistributePolicy@@log_info@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Apache HTTPd has been reloaded successfully"
ifvarclass => "apache_restarted.!apache_restart_failed";
"@@DistributePolicy@@result_error@@root-DP@@root-distributePolicy@@00@@reports@@None@@${g.execRun}##${g.uuid}@#The Apache HTTPd failed to restart"
ifvarclass => "apache_restart_failed";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
############################################################
# Fetch PERL and Curl
############################################################
bundle agent fetchFusionTools
{
packages:
debian::
"curl"
package_policy => "add",
package_method => apt,
classes => rudder_common_classes("fetchFusionTools_install_curl"),
comment => "Installing curl using apt";
redhat::
"curl"
package_policy => "add",
package_method => rudder_yum,
classes => rudder_common_classes("fetchFusionTools_install_curl"),
comment => "Installing curl using yum";
reports:
fetchFusionTools_install_curl_error::
"@@Inventory@@result_error@@inventory-all@@inventory-all@@00@@tools@@None@@${g.execRun}##${g.uuid}@#Installing 'curl' failed. Inventory registration will fail if curl is unavailable";
}
body perms myperms
{
mode => "0700";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
# Definition of variables and classes usefull for all the VM part
# Detect the existence of installed VM containenr on the computer
bundle common virtualMachines
{
vars:
# Files names for the installed VM lists
"VBoxListFile" string => "${g.rudder_var_tmp}/VBoxList.list";
"VMWareListFile" string => "${g.rudder_var_tmp}/VMWareList.list";
"VMWareScript_ServerLocation" string => "${g.rudder_tools}/vmware_info.sh";
# Attribut name for the VM tag in the inventory file
"VBoxAttr" string => "VBox";
"VMWareAttr" string => "VMWare";
# Tools for fetching data
"VMWareScript" string => "${g.inventory_directory}/vmware_info.sh";
windows.!cygwin::
"virtual_box_install_path" string => execresult("${sys.winsysdir}\cmd.exe /c \"echo %VBOX_INSTALL_PATH%\"", "noshell"),
comment => "Looking for VirtualBox environment variables";
cygwin::
"virtual_box_install_path" string => execresult("/usr/bin/echo $VBOX_INSTALL_PATH | /usr/bin/sed ''s/\\/\//g'' ", "useshell"),
comment => "Looking for VirtualBox environment variables";
classes:
linux::
"VirtualBoxInstalled" expression => fileexists("/usr/bin/VBoxManage"),
comment => "Checking installation of VirtualBox";
"VMWareInstalled" expression => fileexists("/usr/bin/wmrun"),
comment => "Checking installation of VMWare";
windows::
"VirtualBoxInstalled" not => regcmp("", "${virtual_box_install_path}");
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#
# This file launch a fusion-inventory agent
# inventory in local.
# If fusion agent is not installed,
# the installation is done
#
# Then the inventory file is improved with external informations (UUID, cf-key, VMs)
bundle agent doInventory
{
vars:
# If curl is available, use it
!windows.curl_installed::
"download_command" string => "${g.rudder_curl} -s -f --proxy '' -o \"${g.rudder_var_tmp}/uuid.txt\" http://${server_info.cfserved}/uuid";
# If not, use minicurl instead
!windows.!curl_installed::
"download_command" string => "${g.minicurl} --get --file \"${g.rudder_var_tmp}/uuid.txt\" --url http://${server_info.cfserved}/uuid";
# On windows, always use curl
windows::
"download_command" string => "\"${g.rudder_base_sbin}\curl\curl.exe\" -s -f --noproxy '${server_info.cfserved}' -o \"${g.rudder_var_tmp}\uuid.txt\" http://${server_info.cfserved}/uuid";
uuid_succesfully_downloaded::
"policy_server_uuid" string => readfile("${g.rudder_var_tmp}/uuid.txt", 50);
classes:
# The force_inventory class may be specified by the user at runtime, or defined here
"force_inventory" expression => fileexists("${g.rudder_base}/etc/force_inventory");
uuid_succesfully_downloaded::
"uuid_valid" expression => regcmp("[a-z0-9-]+","${policy_server_uuid}");
"uuid_validity_checked"
expression => "any",
comment => "This dummy class is just used for ordering the report using !uuid_valid below";
methods:
uuid_valid.(!inventory_sent|force_inventory)::
"any" usebundle => fusionAgent;
"any" usebundle => listInstalledVM;
"any" usebundle => generateExtraInformations;
"any" usebundle => turnUsersToUnicode;
"any" usebundle => addInformationsToInventory;
"any" usebundle => moveInventoryToFinalDestination;
"any" usebundle => sendInventory;
"any" usebundle => cleanForceInventoryFlagFile;
commands:
"${download_command}"
comment => "Getting the uuid from the server",
classes => if_else("uuid_succesfully_downloaded","could_not_download_uuid");
reports:
could_not_download_uuid::
"@@Inventory@@result_error@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not retrieve the UUID of the policy server";
uuid_succesfully_downloaded.uuid_validity_checked.!uuid_valid::
"@@Inventory@@result_error@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not retrieve a valid UUID from the policy server";
# Send reports to confirm this PT's success even if we don't need to send an inventory
inventory_sent::
"@@Inventory@@log_info@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#An inventory was already sent less than 8 hours ago";
!(Night.splaying).!force_inventory::
"@@Inventory@@result_success@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Next inventory scheduled between 00:00 and 06:00";
}
bundle common inventory
{
vars:
windows::
# Files names
"UserListFile_cp" string => "\"${g.rudder_var_tmp}\UserList.tmp\"";
"UserListFile" string => "\"${g.rudder_var_tmp}\UserList.list\"";
any::
"CPUIDFile" string => "${g.rudder_var_tmp}/cpuid.arc";
classes:
windows::
"rudder_inventory_cpuid_tool_present" expression => fileexists("\"${g.rudder_tools}\cpuid-windows-V1.0.vbs\"");
"rudder_inventory_userlist_tool_present" expression => fileexists("${g.rudder_tools}\userlist.bat");
!windows::
"rudder_inventory_cpuid_tool_present" expression => fileexists("${g.rudder_tools}/cpuid-linux-V1.0.sh");
}
bundle agent fusionAgent {
vars:
SuSE.xen_dom0::
"xen_tools_package" string => "xen-tools";
SuSE.xen_domu_pv::
"xen_tools_package" string => "xen-tools-domU";
debian::
"xen_tools_package" string => "xenstore-utils";
(redhat|centos)::
"xen_tools_package" string => "xen";
files:
!windows|cygwin::
"${g.rudder_var_tmp}/inventory/."
create => "true",
comment => "Creating inventory directory",
classes => if_ok("inventoryfoldercreated");
"${g.rudder_var_reports}/."
create => "true";
windows.!cygwin::
"${g.rudder_var_tmp}\inventory\."
create => "true",
comment => "Creating inventory directory",
classes => if_ok("inventoryfoldercreated");
"${g.rudder_var_reports}\."
create => "true";
packages:
xen::
"${xen_tools_package}"
package_policy => "add",
package_method => generic,
classes => cf2_if_else("xen_installed", "cant_install_xen"),
comment => "Installing xen package for extended data";
commands:
!windows.inventoryfoldercreated::
"${g.rudder_base}/bin/run-inventory --local=${g.rudder_var_tmp}/inventory --scan-homedirs"
classes => cf2_if_else("run_inventory", "inventory_failed"),
comment => "Generating inventory, in the temporary folder";
windows::
"\"c:\Program Files\Rudder\sbin\run-inventory.bat\""
args => "--local=\"${g.rudder_var_tmp}\inventory\" --scan-homedirs 2>nul",
contain => in_shell,
classes => cf2_if_else("run_inventory", "inventory_failed"),
comment => "Generating inventory";
reports:
run_inventory::
"@@Inventory@@log_debug@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Running inventory";
inventory_failed::
"@@Inventory@@result_error@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not execute the inventory";
cant_install_curl::
"@@Inventory@@result_error@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not install curl";
cant_install_ocs::
"@@Inventory@@result_error@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not install ocs";
curl_installed::
"@@Inventory@@log_info@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Curl installed";
cant_install_xen::
"@@Inventory@@result_error@@hasPolicyServer-root@@common-root@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not install xen utils on xen systems";
xen_installed::
"@@Inventory@@log_info@@hasPolicyServer-root@@common-root@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Xen utils installed";
}
# List all installed VM on the machine (based on VirtualBox)
# CAUTION : Issue with path containing a whitespace, it's not working with windows
bundle agent listInstalledVM
{
files:
VirtualBoxInstalled::
"${virtualMachines.VBoxListFile}"
create => "true",
edit_line => xmlify(${virtualMachines.VBoxAttr}),
comment => "Converting file into pseudo XML";
VMWareInstalled::
"${virtualMachines.VMWareListFile}"
create => "true",
edit_line => xmlify(${virtualMachines.VMWareAttr}),
comment => "Converting file into pseudo XML";
commands:
linux.VirtualBoxInstalled::
"/usr/bin/VBoxManage"
args => "-q list vms > ${virtualMachines.VBoxListFile}",
contain => outputable,
classes => cf2_if_else("vb_listed", "cant_list_vb"),
comment => "Generating file with list of VM";
windows.VirtualBoxInstalled::
"\"${virtualMachines.virtual_box_install_path}VBoxManage.exe\""
args => "-q list vms > ${virtualMachines.VBoxListFile}",
contain => outputable,
classes => cf2_if_else("vb_listed", "cant_list_vb"),
comment => "Generating file with list of VM";
linux.VMWareInstalled::
"${virtualMachines.VMWareScript}"
contain => outputable,
args => " > ${virtualMachines.VMWareListFile}",
classes => cf2_if_else("vm_listed", "cant_list_vm"),
comment => "Generating file with list of VM";
windows.VMWareInstalled::
"${virtualMachines.VMWareScript}"
contain => outputable,
args => " > ${virtualMachines.VMWareListFile}",
classes => cf2_if_else("vm_listed", "cant_list_vm"),
comment => "Generating file with list of VM";
reports:
cant_list_vm::
"@@Inventory@@log_warn@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not list installed VMWare machines";
cant_list_vb::
"@@Inventory@@log_warn@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not list installed VirtualBox machines";
}
bundle agent generateExtraInformations
{
commands:
windows.rudder_inventory_userlist_tool_present::
"\"${g.rudder_tools}\userlist.bat\""
args => " > ${inventory.UserListFile_cp} ",
contain => outputable,
classes => cf2_if_else("userlist", "userlist_fail"),
comment => "Generating file with list of users";
windows.rudder_inventory_cpuid_tool_present::
"${sys.winsysdir}\cscript.exe"
args => "/Nologo \"${g.rudder_tools}/cpuid-windows-V1.0.vbs\" > \"${inventory.CPUIDFile}\"",
contain => outputable,
classes => cf2_if_else("cpuid", "cpuid_fail"),
comment => "Generating file with CPUID information";
linux.rudder_inventory_cpuid_tool_present::
"${g.rudder_tools}/cpuid-linux-V1.0.sh"
args => " > ${inventory.CPUIDFile}",
contain => outputable,
classes => cf2_if_else("cpuid", "cpuid_fail"),
comment => "Generating file with CPUID information";
android::
"${g.rudder_tools}/cpuid-android-V1.0.sh"
args => " > ${inventory.CPUIDFile}",
contain => outputable,
classes => cf2_if_else("cpuid", "cpuid_fail"),
comment => "Generating file with CPUID information";
reports:
userlist::
"@@Inventory@@log_debug@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Generated the userlist";
cpuid::
"@@Inventory@@log_debug@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Generated the CPUID";
userlist_fail::
"@@Inventory@@result_error@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not generate the user list";
cpuid_fail::
"@@Inventory@@result_error@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not generate the cpuid";
!rudder_inventory_userlist_tool_present::
"@@Inventory@@log_debug@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#The user list generation tool is not present yet. Skipping...";
!rudder_inventory_cpuid_tool_present::
"@@Inventory@@log_debug@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#The CPUID generation tool is not present yet. Skipping...";
}
bundle agent turnUsersToUnicode
{
commands:
windows::
"\"${g.rudder_tools}\iconv.exe\""
args => " -f CP850 -t UTF-8 ${inventory.UserListFile_cp} > ${inventory.UserListFile} ",
contain => outputable_dir("${g.rudder_tools}"),
classes => cf2_if_else("userlist", "userlist_fail"),
comment => "Generating file with list of users in UTF";
reports:
windows::
"@@Inventory@@log_debug@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#This is a windows machine. User list has been converted to Unicode";
}
# adding data to the inventory :
# UUID and CFKey in <DEVICEID>,
# list of VM in <CONTENT>
bundle agent addInformationsToInventory
{
vars:
windows.!cygwin::
"CFKEY" string => execresult("${sys.winsysdir}\cmd.exe /c \"type \"${sys.workdir}\ppkeys\localhost.pub\"\"", "noshell");
"USER" string => getenv("USERNAME", 40);
"RUDDERUUID" string => execresult("${sys.winsysdir}\cscript.exe /Nologo \"${g.rudder_tools}/uuid.vbs\"","noshell");
"polserv_uuid" string => readfile( "${g.rudder_var_tmp}\uuid.txt" , "50" );
# Somehow, using the variable rather than the path fails with readstringlist
"users" slist => { readstringlist("C:\Program Files\Rudder\var\tmp\UserList.list","#.*","[\n| |\r]",50,4000) };
cygwin::
"mywinpath" string => execresult("/usr/bin/echo $WINDIR ", "useshell");
"CFKEY" string => execresult("/usr/bin/cat ${sys.workdir}/ppkeys/localhost.pub", "noshell");
"USER" string => execresult("/usr/bin/whoami", "noshell");
"RUDDERUUID" string => execresult("${sys.winsysdir}\cscript.exe /Nologo ${g.rudder_tools}/uuid.vbs","noshell");
"polserv_uuid" string => readfile( "${g.rudder_var_tmp}/uuid.txt" , "50" );
"users" slist => { readstringlist("${inventory.UserListFile}","#.*","[\n| |\r]",10,4000) };
xen.SuSE.xen_domu_pv::
"VMRUDDERUUID" string => execresult("/bin/xenstore-read vm","noshell");
xen.(centos|redhat|(SuSE.xen_dom0))::
"VMRUDDERUUID" string => execresult("/usr/bin/xenstore-read vm","noshell");
xen.(!SuSE.!centos.!redhat)::
"VMRUDDERUUID" string => execresult("/usr/sbin/xenstore-read vm","noshell");
xen.xenrudderuuid::
"RUDDERUUID" string => "${vmarray[1]}";
linux.!xen::
"RUDDERUUID" string => execresult("/usr/sbin/dmidecode -s system-uuid","noshell");
aix::
"RUDDERUUID" string => execresult("/usr/bin/uname -f", "noshell");
!windows.!android::
"CFKEY" string => execresult("/bin/cat ${sys.workdir}/ppkeys/localhost.pub", "noshell");
"USER" string => execresult("/usr/bin/whoami", "noshell");
"usersnumber" int => readstringarray("userslist","/etc/passwd","#[^\n]*",":",50,16000);
"users" slist => getindices("userslist");
!windows::
"polserv_uuid" string => readfile( "${g.rudder_var_tmp}/uuid.txt" , "50" );
android::
"RUDDERUUID" string => execresult("/system/xbin/sqlite3 /data/data/com.android.providers.settings/databases/settings.db \"select value from secure where name = 'android_id'\"", "noshell");
"CFKEY" string => execresult("/system/bin/cat ${sys.workdir}/ppkeys/localhost.pub", "noshell");
"USER" string => execresult("/system/xbin/whoami", "noshell");
"usersnumber" int => "1";
"users" slist => {"root"};
"android_kernelname" string => "linux";
"android_kernelversion" string => execresult("/system/xbin/uname -r", "noshell");
"android_name" string => "Android";
"android_version" string => execresult("/system/bin/getprop ro.build.version.release", "noshell");
"android_fullname" string => "Android ${android_version}";
"logdate" string => execresult("/system/bin/date '+%Y-%m-%d %H:%M:%S'", "noshell");
classes:
xen::
"xenrudderuuid" expression => regextract("/vm/(.*)", "${VMRUDDERUUID}", "vmarray");
any::
"uuiddefined" expression => isvariable("RUDDERUUID");
files:
windows::
"C:/Progra~1/Rudder/var/tmp/inventory/.*.ocs"
#"${g.esc_rudder_var_tmp}\inventory\.*.ocs"
edit_line => add_information_to_inventory(${RUDDERUUID}, ${CFKEY}, ${USER}, ${polserv_uuid}),
edit_defaults => def_no_backup;
"C:/Progra~1/Rudder/var/tmp/inventory/.*.ocs"
#"${g.esc_rudder_var_tmp}\inventory\.*.ocs"
edit_line => add_users_information_to_inventory(@{addInformationsToInventory.users}),
edit_defaults => def_no_backup;
!windows.uuiddefined::
"${g.rudder_var_tmp}/inventory/.*.ocs"
edit_line => add_information_to_inventory(${RUDDERUUID}, ${CFKEY}, ${USER}, ${polserv_uuid}),
edit_defaults => def_no_backup;
"${g.rudder_var_tmp}/inventory/.*.ocs"
edit_line => add_users_information_to_inventory(@{addInformationsToInventory.users}),
edit_defaults => def_no_backup;
android::
"${g.rudder_var_tmp}/inventory/.*.ocs"
edit_line => add_information_to_android_inventory(${android_fullname}, ${android_kernelname}, ${android_kernelversion}, ${android_name}, ${android_version}),
edit_defaults => def_no_backup;
"${g.rudder_var_tmp}/inventory/.*.ocs"
edit_line => add_accesslog_to_android_inventory(${logdate}),
edit_defaults => def_no_backup;
}
# Move the inventory file in the shared directory
bundle agent moveInventoryToFinalDestination
{
files:
"${g.rudder_inventories}"
copy_from => copy("${g.rudder_var_tmp}/inventory"),
depth_search => recurse_visible(1),
file_select => inventory_files,
comment => "Moving inventory files to the final location";
}
# Send the file to the promises server
bundle agent sendInventory
{
vars:
"download_endpoint" string => "http://${server_info.cfserved}/inventories/";
# If curl is available, use it
!windows.curl_installed::
"download_command_prefix" string => "${g.rudder_curl} -f -s --proxy '' --user ${g.davuser}:${g.davpw} -T";
"download_command_suffix" string => "${download_endpoint}";
# If not, use minicurl instead
!windows.!curl_installed::
"download_command_prefix" string => "${g.minicurl} --put --authentication ${g.davuser}:${g.davpw} --file";
"download_command_suffix" string => "--url ${download_endpoint}";
# On windows, always use curl
windows::
"download_command_prefix" string => "\"${g.rudder_base_sbin}\curl\curl.exe\" -f -s --noproxy '${server_info.cfserved}' --user ${g.davuser}:${g.davpw} -T";
"download_command_suffix" string => "${download_endpoint}";
files:
!windows::
"${g.rudder_inventories}"
transformer => "${download_command_prefix} ${this.promiser} ${download_command_suffix}",
depth_search => recurse_visible(1),
file_select => inventory_files,
classes => persistant_class("inventory_sent", "cant_send_inventory", 480),
comment => "Sending the inventory to the server";
# On windows, the this.promiser variable is not evaluated the same way. We are forced to duplicate this block
windows::
"${g.rudder_inventories}"
transformer => "${download_command_prefix} \"${this.promiser}\" ${download_command_suffix}",
depth_search => recurse_visible(1),
file_select => inventory_files,
classes => persistant_class("inventory_sent", "cant_send_inventory", 480),
comment => "Sending the inventory to the server";
# Once we've successfully sent all inventories, remove them
!windows.inventory_sent.!cant_send_inventory::
"${g.rudder_inventories}"
transformer => "${g.rudder_rm} -f ${this.promiser}",
depth_search => recurse_visible(1),
file_select => inventory_files,
classes => if_else("inventory_file_deleted", "cant_delete_inventory_file"),
comment => "Cleaning up inventory files already sent to the server";
"${g.rudder_var_tmp}/inventory"
transformer => "${g.rudder_rm} -f ${this.promiser}",
depth_search => recurse_visible(1),
file_select => inventory_files,
classes => if_else("inventory_file_deleted", "cant_delete_inventory_file"),
comment => "Cleaning up inventory files already sent to the server";
reports:
inventory_sent::
"@@Inventory@@result_success@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#The inventory has been successfully sent";
cant_send_inventory::
"@@Inventory@@result_error@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not send the inventory";
cant_delete_inventory_file::
"@@Inventory@@log_warn@@inventory-all@@inventory-all@@00@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not delete inventory file after sending to server";
}
#####################################################
#Adding the list of Virtual Machines into the report
#Adding the ids in the report
#####################################################
bundle edit_line add_information_to_inventory(RUDDERUUID, CFKEY, USER, POLSRVUUID)
{
insert_lines:
"<UUID>${g.uuid}</UUID>${const.n}<USER>${USER}</USER>${const.n}<AGENTSNAME>${const.n}</AGENTSNAME>${const.n}<MACHINEID>${RUDDERUUID}</MACHINEID>${const.n}<CFKEY>${CFKEY}</CFKEY>${const.n}<HOSTNAME>${sys.fqhost}</HOSTNAME>${const.n}<POLICY_SERVER>${POLSRVUUID}</POLICY_SERVER>${const.n}"
location => after_deviceid,
insert_type => "preserve_block",
comment => "Add the UUID and CFKEY tags in the inventory file";
any::
"<VMS>${const.n}</VMS>${const.n}<USERSLIST>${const.n}</USERSLIST>"
insert_type => "preserve_block",
location => after_content;
rudder_inventory_cpuid_tool_present::
"${inventory.CPUIDFile}"
insert_type => "file",
location => after_location("<HOSTNAME>"),
comment => "Adding the CPUID data in the inventory file";
nova_edition::
"<AGENTNAME>Nova</AGENTNAME>"
location => after_location("<AGENTSNAME>"),
comment => "Adding the agent data in the inventory file";
community_edition::
"<AGENTNAME>Community</AGENTNAME>"
location => after_location("<AGENTSNAME>"),
comment => "Adding the agent data in the inventory file";
VirtualBoxInstalled::
"${virtualMachines.VBoxListFile}"
insert_type => "file",
location => after_location("<VMS>"),
comment => "Adding the list of VM in the inventory file";
VMWareInstalled::
"${virtualMachines.VMWareListFile}"
insert_type => "file",
location => after_vm,
comment => "Adding the list of VM in the inventory file";
}
bundle edit_line add_information_to_android_inventory(fullname, kernelname, kernelversion, name, version)
{
insert_lines:
android::
"<OPERATINGSYSTEM>${const.n}<FULL_NAME>${fullname}</FULL_NAME>${const.n}<KERNEL_NAME>${kernelname}</KERNEL_NAME>${const.n}<KERNEL_VERSION>${kernelversion}</KERNEL_VERSION>${const.n}<NAME>${name}</NAME>${const.n}<VERSION>${version}</VERSION>${const.n}</OPERATINGSYSTEM>"
location => after_location("<CONTENT>"),
insert_type => "preserve_block",
comment => "Adding the list of OPERATINGSYSTEM part";
}
#this bundle is necessary for OCSInventory (but not for fusioninventory)
bundle edit_line add_accesslog_to_android_inventory(logdate)
{
insert_lines:
android::
"<ACCESSLOG><LOGDATE>${logdate}</LOGDATE></ACCESSLOG>"
location => after_location("</OPERATINGSYSTEM>"),
comment => "Adding log date";
}
bundle edit_line add_users_information_to_inventory(userlist)
{
insert_lines:
(windows.rudder_inventory_userlist_tool_present)|!windows::
"<USER>${userlist}</USER>${const.n}" location => after_users,
comment => "Add the UUID and CFKEY tags in the inventory file";
}
#Locators
body location after_location(pos)
{
select_line_matching => ".*${pos}.*";
before_after => "after";
}
body location after_deviceid
{
select_line_matching => ".*<DEVICEID>.*";
before_after => "after";
}
body location after_content
{
select_line_matching => ".*<CONTENT>.*";
before_after => "after";
}
body location after_vm
{
select_line_matching => ".*<VMS>.*";
before_after => "after";
}
body location after_users
{
select_line_matching => ".*<USERSLIST>.*";
before_after => "after";
}
###############
# Editors
##############
# Convert a simple list in <VM TYPe="vmtype"><NAME>machine_name</NAME><UUID>value<UUID></VM>
bundle edit_line xmlify(ATTR)
{
replace_patterns:
"\"(.*)\" \{(.*)\}"
replace_with=> xmled(${ATTR});
}
body replace_with xmled(attribute)
{
replace_value => "<VM TYPE=\"${attribute}\"><NAME>${match.1}</NAME><UUID>${match.2}</UUID></VM>";
}
# select the inventory files that has the right extension
#I'd like to select also those older than 4 hours (ctime => irange(ago(0,0,0,4,0,0),now);) not working...
# (for some reason, ocs duplicated files over time)
body file_select inventory_files
{
any::
leaf_name => { ".*.ocs" };
file_result => "leaf_name";
#windows::
# leaf_name => { ".*.xml" };
# file_result => "leaf_name";
}
body perms inventory_perms
{
mode => "0700";
}
body file_select one_day_age
#
# we can build old "include", "exclude", and "ignore"
# from these as standard patterns - these bodies can
# form a library of standard patterns
#
{
mtime => irange(ago(1,0,0,0,0,0),ago(0,0,1,0,0,0));
file_result => "mtime";
}
bundle agent cleanForceInventoryFlagFile
{
files:
"${g.rudder_base}/etc/force_inventory"
delete => tidy,
ifvarclass => "inventory_sent"; # if the force inventory file was present, and we successfully sent an inventory, clean up the flag file
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#######################################################
#
# promises.cf
#
#######################################################
bundle common rudder_roles
{
vars:
windows.!cygwin::
"rudder_base" string => "${sys.winprogdir}\Rudder";
"uuid_file" string => "${rudder_base}\etc\uuid.hive";
!windows.!android::
"rudder_base" string => "/opt/rudder";
"uuid_file" string => "${rudder_base}/etc/uuid.hive";
android::
"rudder_base" string => "/data/rudder";
"uuid_file" string => "${rudder_base}/etc/uuid.hive";
any::
"uuid" string => readfile("${uuid_file}", 60);
classes:
# Abort if no uuid is defined
"should_not_continue" not => fileexists("${uuid_file}");
}
body common control
{
any::
output_prefix => "rudder";
inputs => {
@{va.inputs_list}
};
policy_server::
bundlesequence => { @(va.bs),"setup_debian_backports","install_rsyslogd","propagatePromises","root_init_check","root_postgres_check","root_logrotate_check","root_integrity_check","root_technique_reload","root_networks_check","root_alive_check","root_password_check_file","root_password_check_ldap","root_password_check_psql","root_password_check_dav","root_password_restart_jetty", "fetchFusionTools", "virtualMachines", "doInventory", "sendInventoryToCmdb", @(va.end)};
!policy_server::
bundlesequence => { @{va.bs} , "fetchFusionTools", "virtualMachines", "doInventory" , @{va.end}};
}
bundle common va
{
vars:
policy_server::
"bs" slist => { "startExecution", "check_disable_agent", "clean_red_button", "update", "set_red_button", "internal_security", "process_matching", "check_cf_processes", "check_uuid", "check_cron_daemon", "garbage_collection", "check_binaries_freshness"
};
"inputs_list" slist => {
@(va.common_inputs),"distributePolicy/1.0/propagatePromises.cf","distributePolicy/1.0/rsyslogConf.cf","distributePolicy/1.0/initCheck.cf","distributePolicy/1.0/postgresCheck.cf","distributePolicy/1.0/logrotateCheck.cf","distributePolicy/1.0/integrityCheck.cf","distributePolicy/1.0/techniqueReload.cf","distributePolicy/1.0/networkCheck.cf","distributePolicy/1.0/aliveCheck.cf","distributePolicy/1.0/passwordCheck.cf"
};
!policy_server::
"bs" slist => { "startExecution", "check_disable_agent", "update", "internal_security", "process_matching", "check_cf_processes", "check_cron_daemon", "garbage_collection", "check_binaries_freshness"
};
"inputs_list" slist => {
@{va.common_inputs}
};
any::
"end" slist => { "endExecution" };
"common_inputs" slist => {
"common/1.0/cf-served.cf","common/1.0/cfengine_stdlib.cf","common/1.0/rudder_stdlib.cf","common/1.0/rudder_lib.cf","common/1.0/process_matching.cf","common/1.0/internal_security.cf","common/1.0/site.cf","common/1.0/update.cf","inventory/1.0/fetchFusionTools.cf","inventory/1.0/virtualMachines.cf","inventory/1.0/fusionAgent.cf"
};
# definition of the machine roles
classes:
# Policy Server is a machine which delivers promises
"policy_server" expression => strcmp("root", "${rudder_roles.uuid}");
# Root Server is the top policy server machine
"root_server" expression => strcmp("root", "${rudder_roles.uuid}");
}
#########################################################
# Control execution
#########################################################
bundle agent startExecution
{
reports:
cfengine_3::
"@@Common@@log_info@@hasPolicyServer-root@@common-root@@00@@common@@StartRun@@${g.execRun}##${g.uuid}@#Start execution";
}
bundle agent endExecution
{
reports:
cfengine_3::
"@@Common@@log_info@@hasPolicyServer-root@@common-root@@00@@common@@EndRun@@${g.execRun}##${g.uuid}@#End execution";
rudder_promises_generated_error|no_update::
"*********************************************************************************
* rudder-agent could not get an updated configuration from the policy server. *
* This can be caused by a network issue, an unavailable server, or if this *
* node has not yet been accepted in the Rudder root server. *
*********************************************************************************";
}
##########################################################
# Check for "disable-agent" file and cleanly stop and
# warn about this if it is present
##########################################################
bundle agent check_disable_agent
{
vars:
"components" slist => { "cf-serverd", "cf-execd", "cf-monitord" };
classes:
"should_disable_agent" expression => fileexists("${g.rudder_disable_agent_file}");
# Only define this class when we're ready to die - this is a special class name in "abortclasses"
"should_not_continue"
expression => "should_disable_agent",
ifvarclass => "abort_report_done";
processes:
should_disable_agent::
"${sys.workdir}/bin/${components}"
signals => { "term", "kill" };
reports:
should_disable_agent::
"FATAL: The file ${g.rudder_disable_agent_file} is present. Rudder will kill all running daemons and halt immediately."
classes => if_ok("abort_report_done");
}
##########################################################
# Red Button part.
# When the file ${sys.workdir}/inputs/stop exists, we must stop the
# execution of the agent on all client machines
##########################################################
bundle agent clean_red_button()
{
commands:
safe.policy_server::
"${sys.workdir}/bin/cf-runagent"
args => "-Dsafe",
comment => "Propagate the safe information to children";
files:
safe.policy_server::
"${g.rudder_var}/share/[a-f0-9A-F\-]+/rules/cfengine-(community|nova)/stopFile"
delete => tidy,
comment => "Deleting the stop file on clients promises, cfengine is good to go";
safe.!policy_server::
"${sys.workdir}/inputs/stopFile"
delete => tidy,
comment => "Deleting the stop file, cfengine is good to go";
reports:
safe::
"@@Common@@result_repaired@@hasPolicyServer-root@@common-root@@00@@Red Button@@None@@${g.execRun}##${g.uuid}@#Authorizing Cfengine to restart";
}
bundle agent set_red_button()
{
classes:
policy_server::
"danger" expression => fileexists("${g.rudder_var}/share/root/stopFile");
methods:
danger::
"any" usebundle => setStopFile;
danger.policy_server::
"any" usebundle => stopClients;
}
bundle agent setStopFile
{
files:
danger.!policy_server::
"${sys.workdir}/inputs/stopFile"
create => "true";
danger.policy_server::
"${g.rudder_var}/share/[a-f0-9A-F\-]+/rules/cfengine-(community|nova)/stopFile"
create => "true";
reports:
danger.!policy_server::
"@@Common@@result_repaired@@hasPolicyServer-root@@common-root@00@@Red Button@@None@@${g.execRun}##${g.uuid}@#Creating local stop file for this node";
danger.policy_server::
"@@Common@@result_repaired@@hasPolicyServer-root@@common-root@@00@@Red Button@@None@@${g.execRun}##${g.uuid}@#Creating stop files for all clients of this policy server";
}
bundle agent stopClients
{
classes:
policy_server::
"danger" expression => fileexists("${g.rudder_var}/share/root/stopFile");
commands:
danger.policy_server::
"${sys.workdir}/bin/cf-runagent"
args => "-Ddanger",
comment => "Propagate the danger information to children";
reports:
danger.policy_server::
"@@Common@@log_repaired@@hasPolicyServer-root@@common-root@@00@@Red Button@@None@@${g.execRun}##${g.uuid}@#Actively stopping CFEngine operations on all clients of this policy server (via cf-runagent)";
}
bundle agent check_red_button_status()
{
classes:
!policy_server::
"should_not_continue" expression => fileexists("${sys.workdir}/inputs/stopFile");
reports:
!should_not_continue::
"@@Common@@result_success@@hasPolicyServer-root@@common-root@@00@@Red Button@@None@@${g.execRun}##${g.uuid}@#Red Button is not in effect, continuing as normal...";
}
###################################################
# Check that CFengine services are up
###################################################
bundle agent check_cf_processes
{
processes:
!windows::
"${sys.workdir}/bin/cf-serverd" restart_class => "start_server";
"${sys.workdir}/bin/cf-execd" restart_class => "start_executor";
# If there is more than 2 cf-execd's, it means cf-execd is starting to
# go crazy, so we ask politely to these processes to shut down.
"${sys.workdir}/bin/cf-execd"
process_count => check_range("execd", "0","2"),
signals => { "term" },
classes => if_repaired("execd_has_gone_wild"),
comment => "Checking if cf-execd has gone wild";
# The same when there is more than 5 cf-agents
"${sys.workdir}/bin/cf-agent"
process_count => check_range("agent", "0","5"),
signals => { "term" },
classes => if_repaired("agent_has_gone_wild"),
comment => "Checking if cf-agent has gone wild";
# If there is more than 5 cf-execd's/cf-agents, it means that they are really
# going crazy. Let's be a bit less polite and more violent about killing them.
#
# These two promises overlap, because when you go past the 5-limit treshold,
# you still leave a chance for them to die with SIGTERM before the SIGKILL.
#
# Reason: The backend databases that stores the classes and some runtime
# parameters do really not appreciate beeing killed violently and may prevent
# the agent from operating properly.
"${sys.workdir}/bin/cf-execd"
process_count => check_range("execd", "0","5"),
signals => { "kill" },
classes => if_repaired("execd_has_gone_really_wild"),
comment => "Checking if cf-execd has gone really wild";
"${sys.workdir}/bin/cf-agent"
process_count => check_range("agent", "0","8"),
signals => { "kill" },
classes => if_repaired("agent_has_gone_really_wild"),
comment => "Checking if cf-agent has gone really wild";
windows::
# Windows does only implement SIGTERM. Using SIGKILL here makes no sense
"cf-agent"
process_count => check_range("agent", "0","5"),
signals => { "term" },
classes => if_repaired("agent_has_gone_wild"),
comment => "Checking if cf-agent has gone wild";
services:
# By design, there can be only one cf-execd service running on Windows
windows::
"CfengineNovaExec"
service_policy => "start",
service_method => u_bootstart,
comment => "Start the executor windows service now and at boot time";
commands:
start_server::
"${sys.cf_serverd}"
action => u_ifwin_bg,
classes => outcome("server");
start_executor::
"${sys.cf_execd}"
action => u_ifwin_bg,
classes => outcome("executor");
reports:
!execd_has_gone_wild.!execd_has_gone_really_wild.!agent_has_gone_wild.!agent_has_gone_really_wild::
"@@Common@@result_success@@hasPolicyServer-root@@common-root@@00@@Process checking@@None@@${g.execRun}##${g.uuid}@#There is an acceptable number of cf-execd processes (between 0 and 2) and cf-agent processes (between 0 and 5)";
execd_has_gone_wild.!execd_has_gone_really_wild::
"@@Common@@result_repaired@@hasPolicyServer-root@@common-root@@00@@Process checking@@None@@${g.execRun}##${g.uuid}@#Warning, more than 2 cf-execd processes were detected. They have been sent a graceful termination signal.";
execd_has_gone_really_wild::
"@@Common@@result_error@@hasPolicyServer-root@@common-root@@00@@Process checking@@None@@${g.execRun}##${g.uuid}@#ALERT: more than 5 cf-execd processes were detected. Killing processes that do not respect graceful termination signals.";
agent_has_gone_wild.!agent_has_gone_really_wild::
"@@Common@@result_repaired@@hasPolicyServer-root@@common-root@@00@@Process checking@@None@@${g.execRun}##${g.uuid}@#Warning, more than 5 cf-agent processes were detected. They have been sent a graceful termination signal.";
agent_has_gone_really_wild::
"@@Common@@result_error@@hasPolicyServer-root@@common-root@@00@@Process checking@@None@@${g.execRun}##${g.uuid}@#ALERT: more than 8 cf-agent processes were detected. Killing processes that do not respect graceful termination signals.";
}
#######################################################
# UUID file enforcing
bundle agent check_uuid
{
files:
"${g.uuid_file}"
create => "true",
edit_line => enforce_content("${g.uuid}"),
edit_defaults => noempty_backup,
perms => m("644"),
comment => "Setting the uuid variable in a machine";
}
#######################################################
# Check if the cron daemon is running
# This only works with unix flavoured systems too
bundle agent check_cron_daemon
{
vars:
redhat::
"cron_bin" string => "crond$";
"cron_restartcmd" string => "/etc/init.d/crond restart";
ubuntu::
"cron_bin" string => "cron$";
"cron_restartcmd" string => "/etc/init.d/cron restart";
!(redhat|ubuntu)::
"cron_bin" string => "/usr/sbin/cron$";
"cron_restartcmd" string => "/etc/init.d/cron restart";
processes:
!android.!windows::
"${cron_bin}"
restart_class => "restart_crond";
commands:
restart_crond::
"${cron_restartcmd}"
comment => "Restarting crond",
classes => kept_if_else("crond_ok", "crond_restarted" , "crond_failed");
reports:
crond_failed::
"@@Common@@result_error@@hasPolicyServer-root@@common-root@@00@@CRON Daemon@@None@@${g.execRun}##${g.uuid}@#The CRON daemon was not running and could not be restarted";
crond_restarted::
"@@Common@@result_repaired@@hasPolicyServer-root@@common-root@@00@@CRON Daemon@@None@@${g.execRun}##${g.uuid}@#The CRON daemon has been successfully restarted";
!restart_crond.!crond_restarted.!crond_failed.!android::
"@@Common@@result_success@@hasPolicyServer-root@@common-root@@00@@CRON Daemon@@None@@${g.execRun}##${g.uuid}@#The CRON daemon is running";
android|windows::
"@@Common@@result_na@@hasPolicyServer-root@@common-root@@00@CRON Daemon@@None@@${g.execRun}##${g.uuid}@#This is a system without CRON: CRON verifications skipped !";
}
########################################################
# Trash every output report older than 30 days #
########################################################
bundle agent garbage_collection
{
files:
"${sys.workdir}/outputs"
delete => tidy,
file_select => days_old("7"),
depth_search => recurse("inf");
"${g.rudder_var}/modified-files"
delete => tidy,
file_select => days_old("30"),
depth_search => recurse("inf");
}
#######################################################
# Copy the CFengine binaries from the /opt repository
# to the CFengine working directory
bundle agent check_binaries_freshness
{
vars:
community_edition::
"components" slist => { "cf-agent", "cf-serverd", "cf-execd", "cf-monitord", "cf-promises", "cf-runagent", "cf-key", "rpmvercmp" };
files:
!android.!nova_edition::
"${sys.workdir}/bin/${components}"
perms => u_p("700"),
copy_from => cp("${g.rudder_bin}/${components}", "localhost"),
classes => kept_if_else("binaries_fresh", "binaries_rotten", "binaries_missing"),
action => immediate,
comment => "Copying the CFengine binaries from ${g.rudder_sbin}/sbin to ${sys.workdir}/bin";
reports:
binaries_fresh.!binaries_rotten.!binaries_missing::
"@@Common@@result_success@@hasPolicyServer-root@@common-root@@00@@Binaries update@@None@@${g.execRun}##${g.uuid}@#The CFengine binaries in ${sys.workdir}/bin are up to date";
binaries_rotten.!binaries_missing::
"@@Common@@result_repaired@@hasPolicyServer-root@@common-root@@00@@Binaries update@@None@@${g.execRun}##${g.uuid}@#The CFengine binaries have been updated in ${sys.workdir}/bin";
binaries_missing::
"@@Common@@result_error@@hasPolicyServer-root@@common-root@@00@@Binaries update@@None@@${g.execRun}##${g.uuid}@#An error occurred while updating the CFengine binaries in ${sys.workdir}/bin";
android::
"@@Common@@result_success@@hasPolicyServer-root@@common-root@@00@@Binaries update@@None@@${g.execRun}##${g.uuid}@#This is an android machine: no CFEngine binaries update needed";
nova_edition::
"@@Common@@result_na@@hasPolicyServer-root@@common-root@@00@@Binaries update@@None@@${g.execRun}##${g.uuid}@#This is an CFEngine enterprise system: binaries update are handled differently";
}
#######################################################
body agent control
{
# if default runtime is 5 mins we need this for long jobs
ifelapsed => "1";
#define here some environment variables
environment => { "DEBIAN_FRONTEND=noninteractive" };
abortclasses => { "should_not_continue", "could_not_download_uuid" };
agentfacility => "LOG_LOCAL6";
# Repository where to put the copy of modified files
!windows::
default_repository => "/var/rudder/modified-files";
# we can not depend on DNS for mobile devices or NATed device
any::
skipidentify => "true";
}
#######################################################
body executor control
{
splaytime => "1";
schedule => { "Min00", "Min05", "Min10", "Min15", "Min20", "Min25", "Min30", "Min35", "Min40", "Min45", "Min50", "Min55" };
executorfacility => "LOG_DAEMON";
windows::
# CFEngine best practice is to use full paths on Windows
exec_command => "${sys.cf_agent} -f \"${sys.workdir}\inputs\failsafe.cf\" & ${sys.cf_agent}";
!windows::
exec_command => "${sys.cf_agent} -f failsafe.cf && ${sys.cf_agent}";
}
########################################################
#Enforce that the file only contains this information
bundle edit_line enforce_content(str)
{
delete_lines:
"${str}" not_matching => "true";
insert_lines:
"${str}";
}
body process_count system_check_process_count(name, max, min)
{
match_range => irange("${min}","${max}");
out_of_range_define => { "${name}_is_defective" };
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#
# Failsafe file
#
body common control
{
bundlesequence => { "check_lock_db_problem", "init_files", "update" };
inputs => { "common/1.0/update.cf" };
output_prefix => "rudder";
}
body agent control {
# we can not depend on DNS for mobile devices or NATed device
any::
skipidentify => "true";
}
bundle common g
{
vars:
android::
"rudder_base" string => "/data/rudder";
"rudder_var" string => "/data/rudder";
!windows.!android::
"rudder_base" string => "/opt/rudder";
solaris::
"rudder_var" string => "/opt/rudder/var";
!windows.!solaris.!android::
"rudder_var" string => "/var/rudder";
!windows::
"rudder_bin" string => "${rudder_base}/bin";
"rudder_sbin" string => "${rudder_base}/sbin";
"rudder_base_sbin" string => "${rudder_base}/sbin"; #folder where tools are installed
"rudder_tools" string => "${rudder_var}/tools";
"rudder_ncf" string => "${rudder_var}/ncf";
"uuid_file" string => "${rudder_base}/etc/uuid.hive";
windows::
"rudder_base" string => "${sys.winprogdir}\Rudder";
"rudder_bin" string => "${rudder_base}\bin";
"rudder_var" string => "${sys.winprogdir}\Rudder\var";
"rudder_sbin" string => "${rudder_base}\sbin";
"rudder_tools" string => "${rudder_sbin}";
"rudder_ncf" string => "${rudder_var}\ncf";
"uuid_file" string => "${rudder_base}\etc\uuid.hive";
# The time at which the execution started
(linux|cygwin).!(centos_3|redhat_3|centos_4|redhat_4)::
"execRun" string => execresult("/bin/date --rfc-3339=second", "noshell");
(linux|cygwin).(centos_3|redhat_3|centos_4|redhat_4)::
"execRun" string => execresult("/bin/date -u \"+%Y-%m-%d %T+00:00\"", "noshell");
windows.!cygwin::
"execRun" string => execresult("\"${g.rudder_sbin}\getDate.bat\"", "noshell");
android::
"execRun" string => execresult("/system/xbin/date \"+%Y-%m-%d %T+02:00\"", "noshell");
aix::
# AIX's date command doesn't have a "%z" option, so we fake it by using UTC
"execRun" string => execresult("/bin/date -u \"+%Y-%m-%d %T+00:00\"", "noshell");
!linux.!cygwin.!windows.!android.!aix::
"execRun" string => execresult("/bin/date \"+%Y-%m-%d %T%:z\"", "noshell");
any::
"uuid" string => readfile("${g.uuid_file}", 60);
"excludedreps" slist => { "\.X11", ".*kde.*", "\.svn", "perl" };
"rudder_tools_origin" string => "/var/rudder/tools";
"rudder_ncf_origin_common" string => "/usr/share/ncf/tree";
"rudder_ncf_origin_local" string => "/var/rudder/configuration-repository/ncf";
"rudder_tools_updated_origin" string => "${rudder_tools_origin}/rudder_tools_updated";
"rudder_tools_updated" string => "${rudder_tools}/rudder_tools_updated";
}
bundle common rudder_roles
{
classes:
# Abort if no uuid is defined
"should_not_continue" not => fileexists("${g.uuid_file}");
# Policy Server is a machine which delivers promises
"policy_server" expression => strcmp("root","${g.uuid}");
# Root Server is the top policy server machine
"root_server" expression => strcmp("root","${g.uuid}");
# We are in the failsafe phase
"failsafe" expression => "any";
}
############################################
#generate a key if not present
bundle agent init_files
{
vars:
"components" slist => { "cf-agent", "cf-serverd", "cf-execd", "cf-monitord", "cf-promises", "cf-runagent", "cf-key", "cf-hub" };
nova_edition::
"cfengine_install_path" string => "/usr/local";
community_edition::
"cfengine_install_path" string => "${g.rudder_base}";
classes:
"missing_key" not => fileexists("${sys.workdir}/ppkeys/localhost.priv");
files:
cfengine_community.!windows::
"${sys.workdir}/bin/${components}"
perms => u_p("700"),
copy_from => cp("${cfengine_install_path}/bin/${components}","localhost"),
action => immediate;
commands:
cygwin.missing_key::
"${sys.workdir}/bin/cf-key.exe";
windows.missing_key.!cygwin::
"\"${sys.workdir}\bin\cf-key\"";
!windows.!cygwin.missing_key::
"${sys.workdir}/bin/cf-key";
}
# This bundle will check the "last successful inputs update", and if it is older
# than 1 hour, remove cf_lock.db (and only this DB), to give CFEngine a chance
# to run properly again.
bundle agent check_lock_db_problem{
vars:
cfengine_3_0|cfengine_3_1|cfengine_3_2::
"cf_lock_filename" string => "cf_lock.db";
!(cfengine_3_0|cfengine_3_1|cfengine_3_2)::
"cf_lock_filename" string => "cf_lock.tcdb";
files:
# The aim of this promise is to create a class when this file is older
# than one hour. The class can not be created without touching but in
# order to not modifing the mtime we use warn_only.
"${sys.workdir}/last_successful_inputs_update"
file_select => over_an_hour,
touch => "true",
action => warn_only,
classes => success("last_successful_inputs_update_too_old", "last_successful_inputs_update_check_error", "last_successful_inputs_update_ok");
"${sys.workdir}/state/${cf_lock_filename}"
delete => tidy,
ifvarclass => "last_successful_inputs_update_too_old",
classes => success("cf_lock_removed", "cf_lock_error_removing", "cf_lock_not_deleted");
reports:
cf_lock_removed::
"@@Common@@log_repaired@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Promises had not been updated for over an hour, this could indicate a broken lockfile. cf_lock DB file was removed.";
cf_lock_error_removing::
"@@Common@@result_error@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Promises have not been updated for over an hour, this could indicate a broken lockfile, but an error occured when trying to remove it";
}
body file_select over_an_hour()
{
# Select file which are older than one hour
# Use of positive mtime instead of negative one
# In order to avoid corner effects
mtime => irange(ago(0,0,0,1,0,0), now);
file_result => "!mtime";
}
body depth_search recurse(d)
{
depth => "${d}";
}
#perms validation
body perms u_p(p)
{
mode => "${p}";
}
#server may be a list
body copy_from cp(from,server)
{
servers => { "${server}" };
source => "${from}";
compare => "digest";
community_edition::
portnumber => "5309";
}
body action immediate
{
ifelapsed => "0";
}
body depth_search recurse_ignore(d,list)
{
depth => "${d}";
exclude_dirs => { @{list} };
}
body delete tidy
{
dirlinks => "delete";
rmdirs => "true";
}
body action warn_only
{
action_policy => "warn";
ifelapsed => "60";
}
body file_select exclude(name)
{
leaf_name => { "$(name)"};
file_result => "!leaf_name";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#######################################################
#
# Site specific promises
#
#######################################################
bundle common g
{
vars:
android::
"rudder_base" string => "/data/rudder";
"rudder_var" string => "/data/rudder";
"rudder_curl" string => "/system/bin/curl";
"rudder_rm" string => "/system/xbin/rm";
!windows.!android::
"rudder_base" string => "/opt/rudder";
"rudder_curl" string => "/usr/bin/curl";
"rudder_rm" string => "/bin/rm";
solaris::
"rudder_var" string => "/opt/rudder/var";
!solaris.!windows.!android::
"rudder_var" string => "/var/rudder";
!windows::
"rudder_bin" string => "${rudder_base}/bin";
"rudder_sbin" string => "${rudder_base}/sbin";
"rudder_var_tmp" string => "${rudder_var}/tmp"; # tmp generated data
"rudder_base_sbin" string => "${rudder_base}/sbin"; #folder where tools are installed
"rudder_inventories" string => "${rudder_var}/inventories";
"uuid_file" string => "${rudder_base}/etc/uuid.hive";
"rudder_disable_agent_file" string => "${rudder_base}/etc/disable-agent";
"rudder_tools" string => "${rudder_var}/tools";
"rudder_ncf" string => "${rudder_var}/ncf";
"crontab" string => "/etc/crontab";
# DEPRECATED: This variable is used in pre-2.9 Techniques.
"rudder_dependencies" string => "${rudder_var}/tools";
windows::
"rudder_base" string => "${sys.winprogdir}\Rudder";
"rudder_bin" string => "${rudder_base}\bin";
"rudder_sbin" string => "${rudder_base}\sbin";
"rudder_var" string => "${sys.winprogdir}\Rudder\var";
"rudder_var_tmp" string => "${rudder_var}\tmp"; # tmp generated data
"rudder_base_sbin" string => "${rudder_base}\sbin"; #folder where tools are installed
"rudder_inventories" string => "${rudder_var}\inventories";
"rudder_base_sbin_arg" string => "${sys.winprogdir}\Rudder\sbin"; # for the installer command line
"rudder_tools" string => "${rudder_sbin}";
"rudder_ncf" string => "${rudder_base}\ncf";
"escaped_workdir" string => escape("${sys.workdir}");
"rudder_curl" string => "${rudder_base_sbin}\curl\curl.exe";
# DEPRECATED: This variable is used in pre-2.9 Techniques.
"rudder_dependencies" string => "${rudder_sbin}";
"uuid_file" string => "${rudder_base}\etc\uuid.hive";
"rudder_disable_agent_file" string => "${rudder_base}\etc\disable-agent";
any::
"uuid" string => readfile("${g.uuid_file}", 60);
"server_shares_folder" string => "/var/rudder/share/${uuid}/promises/shares";
"rudder_var_reports" string => "${rudder_var}/reports";
"davuser" string => "rudder";
"davpw" string => "rudder";
"minicurl" string => "${rudder_bin}/rudder-perl ${sys.workdir}/inputs/common/utilities/minicurl";
"excludedreps" slist => { "\.X11", ".*kde.*", "\.svn", "perl" };
"rudder_tools_origin" string => "/var/rudder/tools";
"rudder_ncf_common_origin" string => "/var/rudder/ncf/common";
"rudder_ncf_origin_common" string => "/usr/share/ncf/tree";
"rudder_ncf_origin_local" string => "/var/rudder/configuration-repository/ncf";
"rudder_tools_updated_origin" string => "${rudder_tools_origin}/rudder_tools_updated";
"rudder_tools_updated" string => "${rudder_tools}/rudder_tools_updated";
# DEPRECATED: This variable is used in pre-2.9 Techniques.
"rudder_dependencies_origin" string => "/var/rudder/tools";
# The time at which the execution started
(linux|cygwin).!(centos_3|redhat_3|centos_4|redhat_4)::
"execRun" string => execresult("/bin/date --rfc-3339=second", "noshell");
(linux|cygwin).(centos_3|redhat_3|centos_4|redhat_4)::
# We would like to use date's "--rfc-3339=second" option here, but it is not available on older OSes (RHEL 3/4, AIX 5...)
"execRun" string => execresult("/bin/date -u \"+%Y-%m-%d %T+00:00\"", "noshell");
windows.!cygwin::
"execRun" string => execresult("\"${g.rudder_sbin}\getDate.bat\"", "noshell");
android::
"execRun" string => execresult("/system/xbin/date \"+%Y-%m-%d %T%z\" | sed 's/\([-+][0-9][0-9]\)\([0-9][0-9]\)$/\1:\2/'", "useshell");
aix::
# AIX's date command doesn't have a "%z" option, so we fake it by using UTC
"execRun" string => execresult("/bin/date -u \"+%Y-%m-%d %T+00:00\"", "noshell");
!linux.!cygwin.!windows.!android.!aix::
"execRun" string => execresult("/bin/date \"+%Y-%m-%d %T%:z\"", "noshell");
classes:
"curl_installed" expression => isexecutable("${rudder_curl}");
}
#####################################################################################
# Copyright 2011-2012 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#
# This is Rudder's library of common CFEngine functions.
#
# Only bodies and editbundles are to be appended here !!!
#
#####################################################################################
###################################################
# Knowledge from the original stdlib
###################################################
# Uses a specific prefix to avoid collision
# when the stdlib will be updated
###################################################
bundle common rudder_debian_knowledge
# @depends paths
# @brief common Rudder Debian knowledge bundle
#
# This common bundle has useful information about Debian.
{
vars:
"dpkg_compare_equal" string => "/usr/bin/dpkg --compare-versions '${v1}' eq '${v2}'";
"dpkg_compare_less" string => "/usr/bin/dpkg --compare-versions '${v1}' lt '${v2}'";
}
bundle common rudder_rpm_knowledge
# @depends paths
# @brief common Rudder RPM knowledge bundle
#
# This common bundle has useful information about platforms using RPM
{
vars:
"rpm_compare_equal" string => "${sys.workdir}/bin/rpmvercmp '${v1}' eq '${v2}'";
"rpm_compare_less" string => "${sys.workdir}/bin/rpmvercmp '${v1}' lt '${v2}'";
}
###################################################
body depth_search recurse_visible(d)
{
depth => "${d}";
exclude_dirs => { "\..*" };
}
#perms validation
body perms u_p(p)
{
mode => "${p}";
}
#########################################################
#server may be a list
body copy_from cp(from,server)
{
servers => { "${server}" };
source => "${from}";
compare => "digest";
community_edition::
portnumber => "5309";
}
body copy_from scp(from, server,compare,trustkey,preserve,purge)
{
servers => { "${server}" };
source => "${from}";
compare => "${compare}";
encrypt => "true";
verify => "true";
trustkey => "${trustkey}";
preserve => "${preserve}"; #preserver permissions
purge => "${purge}";
community_edition::
portnumber => "5309";
}
# This is an evolved version of copy_from scp that uses local copies if we are
# running on a policy server instead of copying from a localhost remote blindly.
body copy_from rudder_copy_from(from, server,compare,trustkey,preserve,purge) {
source => "${from}";
compare => "${compare}";
encrypt => "true";
verify => "true";
trustkey => "${trustkey}";
preserve => "${preserve}"; # Preserve the permissions
purge => "${purge}";
copy_backup => "timestamp";
!root_server::
servers => { "${server}" };
community_edition::
portnumber => "5309";
}
body copy_from copy(from)
{
source => "${from}";
copy_backup => "false";
preserve => "true";
}
body copy_from copy_digest(from)
{
source => "${from}";
copy_backup => "timestamp";
preserve => "true";
compare => "digest";
}
#########################################################
body classes class_trigger(if,else,kept)
{
promise_kept => { "${kept}" };
promise_repaired => { "${if}" };
repair_failed => { "${else}" };
repair_denied => { "${else}" };
repair_timeout => { "${else}" };
}
#########################################################
body location append
{
before_after => "after";
}
#########################################################
body package_method yum_remi
{
package_changes => "bulk";
package_list_command => "/usr/bin/yum list installed";
package_list_name_regex => "([^.]+).*";
package_list_version_regex => "[^\s]\s+([^\s]+).*";
package_list_arch_regex => "[^.]+\.([^\s]+).*";
package_installed_regex => ".*installed.*";
package_name_convention => "${name}.${arch}";
package_delete_convention => "${name}";
package_add_command => "/usr/bin/yum --enablerepo=remi -y install";
package_delete_command => "/bin/rpm -e";
package_verify_command => "/bin/rpm -V";
}
#perms validation
body perms p(user,mode)
{
owners => { "${user}" };
mode => "${mode}";
}
############################################
body file_select cf3_files
{
leaf_name => { "cf-.*" };
file_result => "leaf_name";
}
#########################################################
body changes lay_trip_wire
{
hash => "best";
report_changes => "content";
update_hashes => "yes";
}
########################################################
body action longjob
{
ifelapsed => "240"; # run only every 4 hours
}
#######################################################
# For the library
#######################################################
body edit_defaults noempty_backup
{
empty_file_before_editing => "false";
edit_backup => "timestamp"; # we want to keep a track of everything
max_file_size => "1024000";
}
body edit_defaults empty_backup
{
empty_file_before_editing => "true";
edit_backup => "timestamp";
max_file_size => "1024000";
}
body edit_defaults def_no_backup
{
empty_file_before_editing => "false";
edit_backup => "false";
max_file_size => "1024000";
}
########################################################
########################################################
bundle edit_line DeleteLinesMatching(regex)
{
delete_lines:
"${regex}"
action => WarnOnly;
}
########################################################
body action WarnOnly
{
action_policy => "warn";
}
########################################
# Bodies
########################################
body replace_with With(x)
{
replace_value => "${x}";
occurrences => "all";
}
########################################
################################
# For commands with a >
################################
body contain outputable
{
useshell => "true";
no_output=> "false";
}
################################
# For commands with a >, in a dir
################################
body contain outputable_dir(dir)
{
useshell => "true";
no_output=> "false";
chdir => "${dir}";
}
################################
# Process is launched ?
################################
body process_count islaunched(class)
{
match_range => irange("1", "500");
in_range_define => { "${class}"};
out_of_range_define => {"no_${class}"};
}
###########################################################################################
# Cancel class
# Cancel every classes passed by argument
##########################################################################################
body classes cancel_all_classes(class_to_cancel) {
cancel_kept => { "${class_to_cancel}" };
cancel_repaired => { "${class_to_cancel}" };
cancel_notkept => { "${class_to_cancel}" };
}
###########################################################################################
# Persistent class
# If the promise is repaired, define repaired for length minutes and undefine failed
# If the promise is not kept, undefine repaired and define failed for length minutes
##########################################################################################
body classes persistant_class(repaired, failed, length)
{
promise_repaired => { "${repaired}" };
repair_failed => { "${failed}" };
repair_denied => { "${failed}" };
repair_timeout => { "${failed}" };
cancel_repaired => {"${failed}"};
cancel_notkept => {"${repaired}"};
persist_time => "${length}";
}
###########################################################################################
# Persistent class
# If the promise is repaired/kept, define repaired for length minutes and undefine failed
# If the promise is not kept, undefine repaired and define failed for length minutes
##########################################################################################
body classes set_persist_classes(repaired, failed, length)
{
promise_kept => { "${repaired}" };
promise_repaired => { "${repaired}" };
repair_failed => { "${failed}" };
repair_denied => { "${failed}" };
repair_timeout => { "${failed}" };
cancel_kept => {"${failed}"};
cancel_repaired => {"${failed}"};
cancel_notkept => {"${repaired}"};
persist_time => "${length}";
}
################################################
# kept_if_else
# set kept if the promise is kept
# yes if repaired
# no if cannot repair
################################################
body classes kept_if_else(kept, yes,no)
{
promise_kept => { "${kept}" };
promise_repaired => { "${yes}" };
repair_failed => { "${no}" };
repair_denied => { "${no}" };
repair_timeout => { "${no}" };
}
#########################################
# Make a local copy with a digest check #
#########################################
body copy_from digest_cp(from)
{
source => "${from}";
compare => "digest";
copylink_patterns => { ".*" };
}
################################################
# kept_if_else with persistant classes
# set kept if the promise is kept
# yes if repaired
# no if cannot repair
################################################
body classes kept_if_else_persist(kept, repaired, failed, persist) {
promise_kept => { "${kept}" };
promise_repaired => { "${repaired}" };
repair_failed => { "${failed}" };
repair_denied => { "${failed}" };
repair_timeout => { "${failed}" };
persist_time => "${persist}";
}
################################################
# Special kept_if_else
# set kept if the promise is kept
# yes if repaired
# no if cannot repair
# Trigger an additionnal promise if repaired
################################################
body classes kept_if_else_hook(kept,yes,no,hook)
{
promise_kept => { "${kept}" };
promise_repaired => { "${yes}", "${hook}" };
repair_failed => { "${no}" };
repair_denied => { "${no}" };
repair_timeout => { "${no}" };
}
################################################
# Simple group adjustment body
################################################
body perms group(group)
{
groups => { "${group}" };
}
################################################
# Same as recurse but without xdev
# and including the current dir
################################################
body depth_search recurse_with_current(d)
{
depth => "${d}";
include_basedir => "true";
xdev => "false";
}
########################################################################
# Mount an NFS share, and allow the user to select if it is persistent #
########################################################################
body mount rudder_nfs(server,source,type,persistence)
{
mount_type => "${type}";
mount_source => "${source}";
mount_server => "${server}";
edit_fstab => "${persistence}";
}
########################################################################
# Same as std_defs, allowing user to specify the file erase policy #
########################################################################
body edit_defaults rudder_empty_select(select)
{
empty_file_before_editing => "${select}";
max_file_size => "1024000";
edit_backup => "timestamp";
}
########################################################################
# Handle a directory recursively, including the dir itself #
########################################################################
body depth_search recurse_withroot(d)
{
depth => "${d}";
# xdev => "true";
include_basedir => "true";
}
########################################################################
# Change group and mode of a file/directory #
########################################################################
body perms mg(mode,group)
{
groups => { "${group}" };
mode => "${mode}";
}
########################################################################
# Select a file using a date AND a pattern #
########################################################################
body file_select date_pattern(age, pattern)
{
mtime => irange("0", ago(0,0,"${age}",0,0,0));
leaf_name => { "${pattern}" };
file_result => "leaf_name.mtime";
}
########################################################################
# Install a package using rug #
########################################################################
body package_method rudder_rug
{
package_changes => "individual";
package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\"";
package_patch_list_command => "/usr/bin/rug patches";
package_list_update_ifelapsed => "240";
package_installed_regex => "i.*";
package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*";
package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_patch_installed_regex => ".*Installed.*|.*Not Applicable.*";
package_patch_name_regex => "[^|]+\|\s+([^\s]+).*";
package_patch_version_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*";
package_name_convention => "${name}";
package_add_command => "/usr/bin/rug install -y";
package_delete_command => "/usr/bin/rug remove -y";
package_update_command => "/usr/bin/rug update -y";
#Unsure about the behavior of this command ...
#package_patch_command => "/usr/bin/rug patch-info";
package_verify_command => "/usr/bin/rug verify -y$"; # $ means no args
# make correct version comparisons
package_version_less_command => "${rudder_rpm_knowledge.rpm_compare_less}";
package_version_equal_command => "${rudder_rpm_knowledge.rpm_compare_equal}";
}
########################################################################
# Install a package using yum but with a check from rpm #
########################################################################
body package_method rudder_yum
{
package_changes => "bulk";
package_list_command => "/bin/rpm -qa --qf '%{name} %{version}-%{release} %{arch}\n'";
package_list_name_regex => "^(\S+?)\s\S+?\s\S+$";
package_list_version_regex => "^\S+?\s(\S+?)\s\S+$";
package_list_arch_regex => "^\S+?\s\S+?\s(\S+)$";
package_installed_regex => ".*";
package_name_convention => "${name}";
package_list_update_command => "/usr/bin/yum --quiet check-update";
package_list_update_ifelapsed => "240";
package_patch_name_regex => "([^.]+).*";
package_patch_version_regex => "[^\s]\s+([^\s]+).*";
package_patch_arch_regex => "[^.]+\.([^\s]+).*";
package_add_command => "/usr/bin/yum -y install";
package_update_command => "/usr/bin/yum -y update";
package_patch_command => "/usr/bin/yum -y update";
package_delete_command => "/bin/rpm -e --nodeps --allmatches";
package_verify_command => "/bin/rpm -V";
# make correct version comparisons
package_version_less_command => "${rudder_rpm_knowledge.rpm_compare_less}";
package_version_equal_command => "${rudder_rpm_knowledge.rpm_compare_equal}";
}
###################################################
# edit_line prepend
###################################################
bundle edit_line prepend(lines)
{
insert_lines:
"${lines}"
comment => "Prepending line : ${lines}",
location => start;
}
###################################################
# edit_line rudder_line_insertion
###################################################
bundle edit_line rudder_line_insertion(lines, location)
{
insert_lines:
"${lines}"
comment => "Adding line: ${lines}",
location => rudder_location_before_after("${location}");
}
#########################################################
body location rudder_location_before_after(location)
{
before_after => "${location}";
}
###################################################
# edit_line replace_line
###################################################
bundle edit_line replace_line(regex,replacement)
{
replace_patterns:
"${regex}"
replace_with => With("${replacement}"),
comment => "Replace every occurence of ${regex} with ${replacement}";
}
###################################################
# edit_line from_to
###################################################
bundle edit_line from_to(from,to)
{
delete_lines:
"${from}" comment => "Reset ${from}";
insert_lines:
"${to}" comment => "Add ${to}";
}
###################################################
# contain in_shell_silent
###################################################
body contain in_shell_silent
{
useshell => "true";
no_output => "true";
}
###################################################
# edit_line insert_rudder_disclaimer
###################################################
bundle edit_line insert_rudder_disclaimer
{
insert_lines:
"## File managed by Rudder - Edit with caution, some changes may disappear (especially passwords) ##"
location => start;
}
#####################################################################################
# Copyright 2012 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#
# Rudder Promise Body and Bundle Library
#
# This library includes standardized bundles and bodies to be used as part of the
# "best practices" in the Techniques writing
#
##################################################
# classes body
##################################################
#
# Automatically defines classes bases on a given prefix
# The classes are defined based on the romises outcome
#
body classes rudder_common_classes(prefix)
{
promise_kept => { "${prefix}_kept" };
promise_repaired => { "${prefix}_repaired" };
repair_failed => { "${prefix}_failed" , "${prefix}_error" };
repair_denied => { "${prefix}_denied" , "${prefix}_error" };
repair_timeout => { "${prefix}_timeout", "${prefix}_error" };
}
##################################################
# files bundles
##################################################
#
# Insert the standard Rudder disclaimer into a file
#
bundle edit_line rudder_common_disclaimer
{
insert_lines:
"#############################################################
### This file is protected by your Rudder infrastructure. ###
### Manually editing the file might lead your Rudder ###
### infrastructure to change back the server's ###
### configuration and/or to raise a compliance alert. ###
#############################################################
"
location => start,
insert_type => "preserve_block";
}
#
# Select files older than X months
#
body file_select rudder_common_months_old(months)
{
mtime => irange(0,ago(0,"${months}",0,0,0,0));
file_result => "mtime";
}
#
# Select files older than X days
#
body file_select rudder_common_days_old(days)
{
mtime => irange(0,ago(0,0,"${days}",0,0,0));
file_result => "mtime";
}
#
# Select files older than X hours
#
body file_select rudder_common_hours_old(hours)
{
mtime => irange(0,ago(0,0,0,"${hours}",0,0));
file_result => "mtime";
}
#
# Select files older than X minutes
#
body file_select rudder_common_minutes_old(minutes)
{
mtime => irange(0,ago(0,0,0,0,"${minutes}",0));
file_result => "mtime";
}
################################################
# Reporting bundles
################################################
#
# Create and send a report to the server
# This bundle takes 6 parameters :
# technique_name : the name of the technique, human readable
# status : the status of the Component, among the following values
# result_success
# result_error
# result_repaired
# log_repaired (for logging only)
# log_warn (for logging only)
# log_info (for logging only)
# log_debug (for logging only)
# log_trace (for logging only)
# identifier : the identifier of the current Rule and Directive
# component_name : the name of the component within the Technique
# component_key : the value of the component reference variable (or None if undefined)
# message : An explanation message understandable by a human
#
bundle agent rudder_common_report(technique_name, status, identifier, component_name, component_key, message)
{
reports:
cfengine_3::
"@@${technique_name}@@${status}@@${identifier}@@${component_name}@@${component_key}@@${g.execRun}##${g.uuid}@#${message}";
}
#
# Automatically create reports based on existing classes starting by
# class_prefix (as defined by the body classes rudder_common_classes)
# Takes 6 parameters
# technique_name : the name of the technique, human readable
# class_prefix : the prefix of a set of classes to reporting on (suffixes with "kept", "repaired" or "error")
# identifier : the identifier of the current Rule and Directive
# component_name : the name of the component within the Technique
# component_key : the value of the component reference variable (None if it does not exists)
# message_prefix : The begining of an explanation message understandable by a human
#
bundle agent rudder_common_reports_generic(technique_name, class_prefix, identifier, component_name, component_key, message_prefix)
{
methods:
"success"
usebundle => rudder_common_report("${technique_name}", "result_success", "${identifier}", "${component_name}", "${component_key}", "${message_prefix} was correct"),
ifvarclass => "${class_prefix}_kept.!${class_prefix}_repaired.!${class_prefix}_error";
"repaired"
usebundle => rudder_common_report("${technique_name}", "result_repaired", "${identifier}", "${component_name}", "${component_key}", "${message_prefix} was repaired"),
ifvarclass => "${class_prefix}_repaired.!${class_prefix}_error";
"error"
usebundle => rudder_common_report("${technique_name}", "result_error", "${identifier}", "${component_name}", "${component_key}", "${message_prefix} could not be repaired"),
ifvarclass => "${class_prefix}_error";
}
############################################################################
# Copyright (C) Cfengine AS
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License LGPL as published by the
# Free Software Foundation; version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# To the extent this program is licensed as part of the Enterprise
# versions of Cfengine, the applicable Commerical Open Source License
# (COSL) may apply to this file if you as a licensee so wish it. See
# included file COSL.txt.
###########################################################################
#
# Cfengine Community Open Promise-Body Library
#
# This initiative started by Cfengine promotes a
# standardized set of names and promise specifications
# for template functionality within Cfengine 3.
#
# The aim is to promote an industry standard for
# naming of configuration patterns, leading to a
# de facto middleware of standardized syntax.
#
# Names should be intuitive and parameters should be
# minimal to assist readability and comprehensibility.
# Contributions to this file are voluntarily given to
# the cfengine community, and are moderated by Cfengine.
# No liability or warranty for misuse is implied.
#
# If you add to this file, please try to make the
# contributions "self-documenting". Comments made
# after the bundle/body statement are retained in
# the online docs
#
# For Cfengine Core: 3.5.0 and older
###################################################
# If you find Cfengine useful, please consider #
# purchasing a commercial version of the software.#
###################################################
###################################################
# edit_line bundles
###################################################
bundle edit_line insert_lines(lines)
{
insert_lines:
"$(lines)"
comment => "Append lines if they don't exist";
}
##
bundle edit_line insert_file(templatefile)
{
insert_lines:
"$(templatefile)"
comment => "Insert the template file into the file being edited",
insert_type => "file";
}
##
bundle edit_line comment_lines_matching(regex,comment)
# Comment lines of a file matching a regex
{
replace_patterns:
"^($(regex))$"
replace_with => comment("$(comment)"),
comment => "Search and replace string";
}
##
bundle edit_line uncomment_lines_matching(regex,comment)
# Uncomment lines of a file where the regex matches
# the text after the comment string
{
replace_patterns:
"^$(comment)\s?($(regex))$"
replace_with => uncomment,
comment => "Uncomment lines matching a regular expression";
}
##
bundle edit_line comment_lines_containing(regex,comment)
# Comment lines of a file containing a regex
{
replace_patterns:
"^((?!$(comment)).*$(regex).*)$"
replace_with => comment("$(comment)"),
comment => "Comment out lines in a file";
}
##
bundle edit_line uncomment_lines_containing(regex,comment)
# Uncomment lines of a file where the regex matches
# the text after the comment string
{
replace_patterns:
"^$(comment)\s?(.*$(regex).*)$"
replace_with => uncomment,
comment => "Uncomment a line containing a fragment";
}
##
bundle edit_line delete_lines_matching(regex)
{
delete_lines:
"$(regex)"
comment => "Delete lines matching regular expressions";
}
##
bundle edit_line warn_lines_matching(regex)
{
delete_lines:
"$(regex)"
comment => "Warn about lines in a file",
action => warn_only;
}
##
bundle edit_line append_if_no_line(str)
{
insert_lines:
"$(str)"
comment => "Append a line to the file if it doesn't already exist";
}
##
bundle edit_line append_if_no_lines(list)
{
insert_lines:
"$(list)"
comment => "Append lines to the file if they don't already exist";
}
##
bundle edit_line replace_line_end(start,end)
#
# Lines starting with "$(start)" will get the ending given in "$(end)",
# whitespaces will be left unmodified.
# For example, replace_line_end("ftp", "2121/tcp") would replace
# "ftp 21/tcp"
# with
# "ftp 2121/tcp"
{
field_edits:
"\s*$(start)\s.*"
comment => "Replace lines with $(this.start) and $(this.end)",
edit_field => line("(^|\s)$(start)\s*", "2", "$(end)","set");
}
##
bundle edit_line append_to_line_end(start,end)
#
# Lines starting with "$(start)" and not ending with "$(end)"
# will get appended with "$(end)", whitespaces will be left unmodified.
# For example, append_to_line_end("kernel", "vga=791") would replace
# "kernel /boot/vmlinuz root=/dev/sda7"
# with
# "kernel /boot/vmlinuz root=/dev/sda7 resume=/dev/sda9 vga=791"
#
# WARNING: Be careful not to have multiple promises matching the same line,
# which would result in the line growing indefinetively.
{
field_edits:
"\s*$(start)\s.*"
comment => "Append lines with $(this.start) and $(this.end)",
edit_field => line("(^|\s)$(start)\s*", "2", "$(end)","append");
}
##
bundle edit_line regex_replace(find,replace)
# You can think of this like a PCRE powered sed.
# Find exactly a regular expression and replace exactly the match with a string.
{
replace_patterns:
"$(find)"
replace_with => value("$(replace)"),
comment => "Search and replace string";
}
##
bundle edit_line resolvconf(search,list)
# search is the search domains with space
# list is an slist of nameserver addresses
{
delete_lines:
"search.*" comment => "Reset search lines from resolver";
"nameserver.*" comment => "Reset nameservers in resolver";
insert_lines:
"search $(search)" comment => "Add search domains to resolver";
"nameserver $(list)" comment => "Add name servers to resolver";
}
##
bundle edit_line manage_variable_values_ini(tab, sectionName)
# Sets the RHS of configuration items in the file of the form
# LHS=RHS
# If the line is commented out with #, it gets uncommented first.
# Adds a new line if none exists.
# Removes any variable value pairs not defined for the ini section
# The argument is an associative array containing tab[SectionName][LHS]="RHS"
# don't change value when the RHS is dontchange
# Based on set_variable_values_ini
# Added delete lines section to empty out undefined variable values for INI section
# CAUTION : for it to work nicely, you should use Cfengine with the commit n°3229
# otherwise you may risk a segfault
#
# If you are running 3.2.1 or earlier or more specifically git commit # or
# earlier you can use this to work around the segfault bug.
# vars:
# "$(file)"
# edit_line => append_if_no_line("[#EOF#]"),
# create => "true",
# comment => "Work around bug<bug#here> where eof did not mean end
# of section and thus cannot select a region. This promise
# should be placed before your call to this bundle";
# "$(file)"
# edit_line => manage_variable_values_ini("context.array", "SectionName"),
# create => "true",
# comment => "Set the variale values only in the specified ini region";
#
{
vars:
"index" slist => getindices("$(tab)[$(sectionName)]");
# Be careful if the index string contains funny chars
"cindex[$(index)]" string => canonify("$(index)");
classes:
"edit_$(cindex[$(index)])" not => strcmp("$($(tab)[$(sectionName)][$(index)])","dontchange"),
comment => "Create conditions to make changes";
field_edits:
# If the line is there, but commented out, first uncomment it
"#+\s*$(index)\s*=.*"
select_region => INI_section("$(sectionName)"),
edit_field => col("=","1","$(index)","set"),
ifvarclass => "edit_$(cindex[$(index)])";
# match a line starting like the key something
"$(index)\s*=.*"
edit_field => col("=","2","$($(tab)[$(sectionName)][$(index)])","set"),
select_region => INI_section("$(sectionName)"),
classes => if_ok("manage_variable_values_ini_not_$(cindex[$(index)])"),
ifvarclass => "edit_$(cindex[$(index)])";
delete_lines:
".*"
select_region => INI_section("$(sectionName)"),
comment => "Remove all entries in the region so there are no extra entries";
insert_lines:
"[$(sectionName)]"
location => start,
comment => "Insert lines";
"$(index)=$($(tab)[$(sectionName)][$(index)])"
select_region => INI_section("$(sectionName)"),
ifvarclass => "!manage_variable_values_ini_not_$(cindex[$(index)]).edit_$(cindex[$(index)])";
}
##
bundle edit_line set_variable_values_ini(tab, sectionName)
# Sets the RHS of configuration items in the file of the form
# LHS=RHS
# If the line is commented out with #, it gets uncommented first.
# Adds a new line if none exists.
# The argument is an associative array containing tab[SectionName][LHS]="RHS"
# don't change value when the RHS is dontchange
# Based on set_variable_values from cfengine_stdlib.cf, modified to
# use section to define were to write, and to handle commented-out lines.
# CAUTION : for it to work nicely, you should use Cfengine with the commit n°3229
# otherwise you may risk a segfault
#
# If you are running 3.2.1 or earlier or more specifically git commit # or
# earlier you can use this to work around the segfault bug.
# vars:
# "$(file)"
# edit_line => append_if_no_line("[#EOF#]"),
# create => "true",
# comment => "Work around bug<bug#here> where eof did not mean end
# of section and thus cannot select a region. This promise
# should be placed before your call to this bundle";
# "$(file)"
# edit_line => set_variable_values_ini("context.array", "SectionName"),
# create => "true",
# comment => "Set the variale values only in the specified ini region";
#
{
vars:
"index" slist => getindices("$(tab)[$(sectionName)]");
# Be careful if the index string contains funny chars
"cindex[$(index)]" string => canonify("$(index)");
classes:
"edit_$(cindex[$(index)])" not => strcmp("$($(tab)[$(sectionName)][$(index)])","dontchange"),
comment => "Create conditions to make changes";
field_edits:
# If the line is there, but commented out, first uncomment it
"#+\s*$(index)\s*=.*"
select_region => INI_section("$(sectionName)"),
edit_field => col("=","1","$(index)","set"),
ifvarclass => "edit_$(cindex[$(index)])";
# match a line starting like the key something
"$(index)\s*=.*"
edit_field => col("=","2","$($(tab)[$(sectionName)][$(index)])","set"),
select_region => INI_section("$(sectionName)"),
classes => if_ok("set_variable_values_ini_not_$(cindex[$(index)])"),
ifvarclass => "edit_$(cindex[$(index)])";
insert_lines:
"[$(sectionName)]"
location => start,
comment => "Insert lines";
"$(index)=$($(tab)[$(sectionName)][$(index)])"
select_region => INI_section("$(sectionName)"),
ifvarclass => "!set_variable_values_ini_not_$(cindex[$(index)]).edit_$(cindex[$(index)])";
}
bundle edit_line set_quoted_values(v)
{
# Sets the RHS of variables in shell-like files
# that is:
# LHS="RHS"
# Adds a new line if no LHS exists
# repairs RHS values if one does exist
# If the line is commented out with #, it gets uncommented first.
#
# To use:
# 1) Define an array, where the keys are the LHS and the values are the RHS
# "stuff[lhs-1]" string => "rhs1";
# "stuff[lhs-2]" string => "rhs2";
# 2) The parameter passed to the edit_line promise is the fully qualified
# name of the array (i.e., "bundlename.stuff") WITHOUT any "$" or "@"
vars:
"index" slist => getindices("$(v)");
# Be careful if the index string contains funny chars
"cindex[$(index)]" string => canonify("$(index)");
field_edits:
# If the line is there, but commented out, first uncomment it
"#+\s*$(index)\s*=.*"
edit_field => col("=","1","$(index)","set");
# match a line starting like the key = something
"\s*$(index)\s*=.*"
edit_field => col("=","2",'"$($(v)[$(index)])"',"set"),
classes => if_ok("$(cindex[$(index)])_in_file"),
comment => "Match a line starting like key = something";
insert_lines:
'$(index)="$($(v)[$(index)])"'
comment => "Insert a variable definition",
ifvarclass => "!$(cindex[$(index)])_in_file";
}
##
bundle edit_line set_variable_values(v)
# Sets the RHS of variables in the file of the form
# LHS = RHS
# Adds a new line if no LHS exists, repairs RHS values if one does exist
#
# To use:
# 1) Define an array, where the keys are the LHS and the values are the RHS
# "stuff[lhs-1]" string => "rhs1";
# "stuff[lhs-2]" string => "rhs2";
# 2) The parameter passed to the edit_line promise is the fully qualified
# name of the array (i.e., "bundlename.stuff") WITHOUT any "$" or "@"
{
vars:
"index" slist => getindices("$(v)");
# Be careful if the index string contains funny chars
"cindex[$(index)]" string => canonify("$(index)");
"cv" string => canonify("$(v)");
field_edits:
# match a line starting like the key = something
"\s*$(index)\s*=.*"
edit_field => col("=","2","$($(v)[$(index)])","set"),
classes => if_ok("$(cv)_$(cindex[$(index)])_in_file"),
comment => "Match a line starting like key = something";
insert_lines:
"$(index)=$($(v)[$(index)])"
comment => "Insert a variable definition",
ifvarclass => "!$(cv)_$(cindex[$(index)])_in_file";
}
bundle edit_line set_config_values(v)
# Sets the RHS of configuration items in the file of the form
# LHS RHS
# If the line is commented out with #, it gets uncommented first.
# Adds a new line if none exists.
# The argument is the fully-qualified name of an associative array containing v[LHS]="rhs"
{
vars:
"index" slist => getindices("$(v)");
# Be careful if the index string contains funny chars
"cindex[$(index)]" string => canonify("$(index)");
replace_patterns:
# If the line is there, maybe commented out, uncomment and replace with
# the correct value
"^\s*($(index)\s+(?!$($(v)[$(index)])$).*|# ?$(index)\s+.*)$"
comment => "Correct the value",
replace_with => value("$(index) $($(v)[$(index)])"),
classes => always("replace_attempted_$(cindex[$(index)])");
insert_lines:
"$(index) $($(v)[$(index)])"
ifvarclass => "replace_attempted_$(cindex[$(index)])";
}
bundle edit_line set_config_values_matching(v,pat)
# Sets the RHS of configuration items in the file of the form
# LHS RHS
# If the line is commented out with #, it gets uncommented first.
# Adds a new line if none exists.
# Only elements of "v" that match the regex "pat" are used
# The argument is the fully-qualified name of an associative array containing v[LHS]="rhs"
{
vars:
"allparams" slist => getindices("$(v)");
"index" slist => grep("$(pat)", "allparams");
# Be careful if the index string contains funny chars
"cindex[$(index)]" string => canonify("$(index)");
replace_patterns:
# If the line is there, maybe commented out, uncomment and replace with
# the correct value
"^\s*($(index)\s+(?!$($(v)[$(index)])).*|# ?$(index)\s+.*)$"
comment => "Correct the value",
replace_with => value("$(index) $($(v)[$(index)])"),
classes => always("replace_attempted_$(cindex[$(index)])");
insert_lines:
"$(index) $($(v)[$(index)])"
ifvarclass => "replace_attempted_$(cindex[$(index)])";
}
##
bundle edit_line maintain_key_values(v,sep)
# Contributed by David Lee
# Purpose: Sets the RHS of configuration items with an giving separator
{
vars:
"index" slist => getindices("$(v)");
# Be careful if the index string contains funny chars
"cindex[$(index)]" string => canonify("$(index)");
# Matching pattern for line (basically key-and-separator)
"keypat[$(index)]" string => "\s*$(index)\s*$(sep)\s*";
# Values may contain regexps. Escape them for replace_pattern matching.
"ve[$(index)]" string => escape("$($(v)[$(index)])");
classes:
"$(cindex[$(index)])_key_in_file"
comment => "Dynamic Class created if patterns matching",
expression => regline("^$(keypat[$(index)]).*", "$(edit.filename)");
replace_patterns:
# For convergence need to use negative lookahead on value:
# "key sep (?!value).*"
"^($(keypat[$(index)]))(?!$(ve[$(index)])$).*"
comment => "Replace definition of $(index)",
replace_with => value("$(match.1)$($(v)[$(index)])");
insert_lines:
"$(index)$(sep)$($(v)[$(index)])"
comment => "Insert definition of $(index)",
ifvarclass => "!$(cindex[$(index)])_key_in_file";
}
##
bundle edit_line append_users_starting(v)
# For adding to /etc/passwd or etc/shadow, needs
# an array v[username] string => "line..."
{
vars:
"index" slist => getindices("$(v)");
classes:
"add_$(index)" not => userexists("$(index)"),
comment => "Class created if user does not exist";
insert_lines:
"$($(v)[$(index)])"
comment => "Append users into a password file format",
ifvarclass => "add_$(index)";
}
##
bundle edit_line append_groups_starting(v)
# For adding groups to /etc/group, needs
# an array v[groupname] string => "line..."
{
vars:
"index" slist => getindices("$(v)");
classes:
"add_$(index)" not => groupexists("$(index)"),
comment => "Class created if group does not exist";
insert_lines:
"$($(v)[$(index)])"
comment => "Append users into a group file format",
ifvarclass => "add_$(index)";
}
##
bundle edit_line set_colon_field(key,field,val)
# Set the value of field number "field" of the
# line whose first field is "key", in a colon-separated file.
{
field_edits:
"$(key):.*"
comment => "Edit a colon-separated file, using the first field as a key",
edit_field => col(":","$(field)","$(val)","set");
}
##
bundle edit_line set_user_field(user,field,val)
# Set the value of field number "field" in
# a :-field formatted file like /etc/passwd
{
field_edits:
"$(user):.*"
comment => "Edit a user attribute in the password file",
edit_field => col(":","$(field)","$(val)","set");
}
##
bundle edit_line append_user_field(group,field,allusers)
# For adding users to to a file like /etc/group
# at field position "field", comma separated subfields
{
vars:
"val" slist => { @(allusers) };
field_edits:
"$(group):.*"
comment => "Append users into a password file format",
edit_field => col(":","$(field)","$(val)","alphanum");
}
##
bundle edit_line expand_template(templatefile)
# Read in the named text file and expand $(var)
# inside the file
{
insert_lines:
"$(templatefile)"
insert_type => "file",
comment => "Expand variables in the template file",
expand_scalars => "true";
}
bundle edit_line replace_or_add(pattern,line)
# Replace a pattern in a file with a single line.
# If the pattern is not found, add the line to the file.
# The pattern must match the whole line (it is automatically
# anchored to the start and end of the line) to avoid
# ambiguity.
{
vars:
"cline" string => canonify("$(line)");
"eline" string => escape("$(line)");
replace_patterns:
"^(?!$(eline)$)$(pattern)$"
comment => "Replace a pattern here",
replace_with => value("$(line)"),
classes => always("replace_done_$(cline)");
insert_lines:
"$(line)"
ifvarclass => "replace_done_$(cline)";
}
##
bundle agent cronjob(commands,user,hours,mins)
# For adding lines to crontab for a user
# methods:
# "cron" usebundle => cronjob("/bin/ls","mark","*","5,10");
{
vars:
SuSE::
"crontab" string => "/var/spool/cron/tabs";
redhat|fedora::
"crontab" string => "/var/spool/cron";
freebsd::
"crontab" string => "/var/cron/tabs";
!(SuSE|redhat|fedora|freebsd)::
"crontab" string => "/var/spool/cron/crontabs";
files:
!windows::
"$(crontab)/$(user)"
comment => "A user's regular batch jobs are added to this file",
create => "true",
edit_line => append_if_no_line("$(mins) $(hours) * * * $(commands)"),
perms => mo("600","$(user)"),
classes => if_repaired("changed_crontab");
processes:
changed_crontab::
"cron"
comment => "Most crons need to be huped after file changes",
signals => { "hup" };
}
##-------------------------------------------------------
## editing bodies
##-------------------------------------------------------
body edit_field quoted_var(newval,method)
{
field_separator => "\"";
select_field => "2";
value_separator => " ";
field_value => "$(newval)";
field_operation => "$(method)";
extend_fields => "false";
allow_blank_fields => "true";
}
##
body edit_field col(split,col,newval,method)
{
field_separator => "$(split)";
select_field => "$(col)";
value_separator => ",";
field_value => "$(newval)";
field_operation => "$(method)";
extend_fields => "true";
allow_blank_fields => "true";
}
##
body edit_field line(split,col,newval,method)
{
field_separator => "$(split)";
select_field => "$(col)";
value_separator => " ";
field_value => "$(newval)";
field_operation => "$(method)";
extend_fields => "true";
allow_blank_fields => "true";
}
##
body replace_with value(x)
{
replace_value => "$(x)";
occurrences => "all";
}
##
body select_region INI_section(x)
{
select_start => "\[$(x)\]\s*";
select_end => "\[.*\]\s*";
}
##-------------------------------------------------------
## edit_defaults
##-------------------------------------------------------
body edit_defaults std_defs
{
empty_file_before_editing => "false";
edit_backup => "false";
#max_file_size => "300000";
}
##
body edit_defaults empty
{
empty_file_before_editing => "true";
edit_backup => "false";
#max_file_size => "300000";
}
##
body edit_defaults no_backup
{
edit_backup => "false";
}
##
body edit_defaults backup_timestamp
{
empty_file_before_editing => "false";
edit_backup => "timestamp";
#max_file_size => "300000";
}
##-------------------------------------------------------
## location
##-------------------------------------------------------
body location start
{
before_after => "before";
}
##
body location after(str)
{
before_after => "after";
select_line_matching => "$(str)";
}
##
body location before(str)
{
before_after => "before";
select_line_matching => "$(str)";
}
##-------------------------------------------------------
## replace_with
##-------------------------------------------------------
##
body replace_with comment(c)
{
replace_value => "$(c) $(match.1)";
occurrences => "all";
}
##
body replace_with uncomment
{
replace_value => "$(match.1)";
occurrences => "all";
}
####################################################
## agent bodyparts
####################################################
##-------------------------------------------------------
## action
##-------------------------------------------------------
body action if_elapsed(x)
{
ifelapsed => "$(x)";
expireafter => "$(x)";
}
##
body action if_elapsed_day
{
ifelapsed => "1440"; # 60 x 24
expireafter => "1400";
}
##
body action measure_performance(x)
{
measurement_class => "Detect changes in $(this.promiser)";
ifelapsed => "$(x)";
expireafter => "$(x)";
}
##
body action warn_only
{
action_policy => "warn";
ifelapsed => "60";
}
##
body action bg(elapsed,expire)
{
ifelapsed => "$(elapsed)";
expireafter => "$(expire)";
background => "true";
}
##
body action ifwin_bg
{
windows::
background => "true";
}
##
body action immediate
{
ifelapsed => "0";
}
##
body action policy(p)
{
action_policy => "$(p)";
}
##
# Log a message to log=[/file|stdout]
body action log_repaired(log,message)
{
log_string => "$(sys.date), $(message)";
log_repaired => "$(log)";
}
###
body action log_verbose
{
log_level => "verbose";
}
##-------------------------------------------------------
## contain
##-------------------------------------------------------
body contain silent
{
no_output => "true";
}
##
body contain in_dir(s)
{
chdir => "$(s)";
}
##
body contain in_dir_shell(s)
{
chdir => "$(s)";
useshell => "true"; # canonical "useshell" but this is backwards-compatible
}
##
body contain silent_in_dir(s)
{
chdir => "$(s)";
no_output => "true";
}
##
body contain in_shell
{
useshell => "true"; # canonical "useshell" but this is backwards-compatible
}
##
body contain in_shell_bg
{
useshell => "true"; # canonical "useshell" but this is backwards-compatible
}
##
body contain in_shell_and_silent
{
useshell => "true"; # canonical "useshell" but this is backwards-compatible
no_output => "true";
}
##
body contain in_dir_shell_and_silent(dir)
{
useshell => "true"; # canonical "useshell" but this is backwards-compatible
no_output => "true";
chdir => "$(dir)";
}
##
body contain setuid(x)
{
exec_owner => "$(x)";
useshell => "false"; # canonical "noshell" but this is backwards-compatible
}
##
body contain setuid_sh(x)
{
exec_owner => "$(x)";
useshell => "true"; # canonical "useshell" but this is backwards-compatible
}
##
body contain setuidgid_sh(owner,group)
{
exec_owner => "$(owner)";
exec_group => "$(group)";
useshell => "true"; # canonical "useshell" but this is backwards-compatible
}
##
body contain jail(owner,root,dir)
{
exec_owner => "$(owner)";
useshell => "true"; # canonical "useshell" but this is backwards-compatible
chdir => "$(dir)";
chroot => "$(root)";
}
##
body contain setuid_umask(uid, umask)
###################################################
# | Files | Directories #
###################################################
# Umask | Octal Symbolic | Octal Symbolic #
########+#####################+###################+
# 000 | 666 (rw-rw-rw-) | 777 (rwxrwxrwx)
# 002 | 664 (rw-rw-r--) | 775 (rwxrwxr-x)
# 022 | 644 (rw-r--r--) | 755 (rwxr-xr-x)
# 027 | 640 (rw-r-----) | 750 (rwxr-x---)
# 077 | 600 (rw-------) | 700 (rwx------)
# 277 | 400 (r--------) | 500 (r-x------)
{
exec_owner => "$(uid)";
umask => "$(umask)";
}
##-------------------------------------------------------
## classes
##-------------------------------------------------------
body classes if_repaired(x)
{
promise_repaired => { "$(x)" };
}
##
body classes if_else(yes,no)
{
promise_kept => { "$(yes)" };
promise_repaired => { "$(yes)" };
repair_failed => { "$(no)" };
repair_denied => { "$(no)" };
repair_timeout => { "$(no)" };
}
##
body classes cf2_if_else(yes,no)
# meant to match cf2 semantics
{
promise_repaired => { "$(yes)" };
repair_failed => { "$(no)" };
repair_denied => { "$(no)" };
repair_timeout => { "$(no)" };
}
##
body classes if_notkept(x)
{
repair_failed => { "$(x)" };
repair_denied => { "$(x)" };
repair_timeout => { "$(x)" };
}
##
body classes if_ok(x)
{
promise_repaired => { "$(x)" };
promise_kept => { "$(x)" };
}
##
body classes if_ok_cancel(x)
{
cancel_repaired => { "$(x)" };
cancel_kept => { "$(x)" };
}
##
body classes cmd_repair(code,cl)
{
repaired_returncodes => { "$(code)" };
promise_repaired => { "$(cl)" };
}
body classes classes_generic(x)
# Define x prefixed/suffixed with promise outcome
{
promise_repaired => { "promise_repaired_$(x)", "$(x)_repaired", "$(x)_ok", "$(x)_reached" };
repair_failed => { "repair_failed_$(x)", "$(x)_failed", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached" };
repair_denied => { "repair_denied_$(x)", "$(x)_denied", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached" };
repair_timeout => { "repair_timeout_$(x)", "$(x)_timeout", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached" };
promise_kept => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached" };
}
##-------------------------------------------------------
## Persistent classes
##-------------------------------------------------------
body classes state_repaired(x)
{
promise_repaired => { "$(x)" };
persist_time => "10";
}
##
body classes enumerate(x)
#
# This is used by commercial editions to count
# instances of jobs in a cluster
#
{
promise_repaired => { "mXC_$(x)" };
promise_kept => { "mXC_$(x)" };
persist_time => "15";
}
##
body classes always(x)
# Define a class no matter what the outcome of the promise is
{
promise_repaired => { "$(x)" };
promise_kept => { "$(x)" };
repair_failed => { "$(x)" };
repair_denied => { "$(x)" };
repair_timeout => { "$(x)" };
}
###################################################
# agent bundles
###################################################
##..................................................
## files promises
##..................................................
# this is a workaround for the issue that recurse_with_base precludes
# a file from being deleted
bundle agent rm_rf(name)
{
classes:
"isdir" expression => isdir($(name));
files:
isdir::
"$(name)"
file_select => all,
depth_search => recurse_with_base(999),
delete => tidy;
!isdir::
"$(name)" delete => tidy;
}
##-------------------------------------------------------
## copy_from
##-------------------------------------------------------
body copy_from secure_cp(from,server)
{
source => "$(from)";
servers => { "$(server)" };
compare => "digest";
encrypt => "true";
verify => "true";
}
##
body copy_from remote_cp(from,server)
{
servers => { "$(server)" };
source => "$(from)";
compare => "mtime";
}
##
body copy_from remote_dcp(from,server)
{
servers => { "$(server)" };
source => "$(from)";
compare => "digest";
}
##
body copy_from local_cp(from)
{
source => "$(from)";
}
##
body copy_from local_dcp(from)
{
source => "$(from)";
compare => "digest";
}
##
body copy_from perms_cp(from)
{
source => "$(from)";
preserve => "true";
}
body copy_from backup_local_cp(from)
# Local copy, keeping a backup of old versions
{
source => "$(from)";
copy_backup => "timestamp";
}
##
# Copy only if the file does not already exist, i.e. seed the placement
body copy_from seed_cp(from)
{
source => "$(from)";
compare => "exists";
}
##
body copy_from sync_cp(from,server)
{
servers => { "$(server)" };
source => "$(from)";
purge => "true";
preserve => "true";
type_check => "false";
}
##
body copy_from no_backup_cp(from)
{
source => "$(from)";
copy_backup => "false";
}
##
body copy_from no_backup_dcp(from)
{
source => "$(from)";
copy_backup => "false";
compare => "digest";
}
##
body copy_from no_backup_rcp(from,server)
{
servers => { "$(server)" };
source => "$(from)";
compare => "mtime";
copy_backup => "false";
}
##-------------------------------------------------------
## link_from
##-------------------------------------------------------
body link_from ln_s(x)
{
link_type => "symlink";
source => "$(x)";
when_no_source => "force";
}
##
body link_from linkchildren(tofile)
{
source => "$(tofile)";
link_type => "symlink";
when_no_source => "force";
link_children => "true";
when_linking_children => "if_no_such_file"; # "override_file";
}
##-------------------------------------------------------
## perms
##-------------------------------------------------------
body perms m(mode)
{
mode => "$(mode)";
}
##
body perms mo(mode,user)
{
owners => { "$(user)" };
mode => "$(mode)";
}
##
body perms mog(mode,user,group)
{
owners => { "$(user)" };
groups => { "$(group)" };
mode => "$(mode)";
}
##
body perms og(u,g)
{
owners => { "$(u)" };
groups => { "$(g)" };
}
##
body perms owner(user)
{
owners => { "$(user)" };
}
##-------------------------------------------------------
## ACLS (extended Unix perms)
##-------------------------------------------------------
body acl access_generic(acl)
# default/inherited ACLs are left unchanged,
# applicable for both files and directories on all platforms
{
acl_method => "overwrite";
aces => { "@(acl)" };
windows::
acl_type => "ntfs";
!windows::
acl_type => "posix";
}
##
body acl ntfs(acl)
{
acl_type => "ntfs";
acl_method => "overwrite";
aces => { "@(acl)" };
}
##
body acl strict
# NOTE: May need to take ownership of file/dir
# to be sure no-one else is allowed access
{
acl_method => "overwrite";
windows::
aces => { "user:Administrator:rwx" };
!windows::
aces => { "user:root:rwx" };
}
##-------------------------------------------------------
## depth_search
##-------------------------------------------------------
body depth_search recurse(d)
{
depth => "$(d)";
xdev => "true";
}
##
body depth_search recurse_ignore(d,list)
{
depth => "$(d)";
exclude_dirs => { @(list) };
}
##
body depth_search include_base
{
include_basedir => "true";
}
body depth_search recurse_with_base(d)
{
depth => "$(d)";
xdev => "true";
include_basedir => "true";
}
##-------------------------------------------------------
## delete
##-------------------------------------------------------
body delete tidy
{
dirlinks => "delete";
rmdirs => "true";
}
##-------------------------------------------------------
## rename
##-------------------------------------------------------
body rename disable
{
disable => "true";
}
##
body rename rotate(level)
{
rotate => "$(level)";
}
##
body rename to(file)
{
newname => "$(file)";
}
##-------------------------------------------------------
## file_select
##-------------------------------------------------------
body file_select name_age(name,days)
{
leaf_name => { "$(name)" };
mtime => irange(0,ago(0,0,"$(days)",0,0,0));
file_result => "mtime.leaf_name";
}
##
body file_select days_old(days)
{
mtime => irange(0,ago(0,0,"$(days)",0,0,0));
file_result => "mtime";
}
##
body file_select size_range(from,to)
{
search_size => irange("$(from)","$(to)");
file_result => "size";
}
##
body file_select exclude(name)
{
leaf_name => { "$(name)"};
file_result => "!leaf_name";
}
##
body file_select plain
{
file_types => { "plain" };
file_result => "file_types";
}
body file_select dirs
{
file_types => { "dir" };
file_result => "file_types";
}
##
body file_select by_name(names)
{
leaf_name => { @(names)};
file_result => "leaf_name";
}
##
body file_select ex_list(names)
{
leaf_name => { @(names)};
file_result => "!leaf_name";
}
##
body file_select all
{
leaf_name => { ".*" };
file_result => "leaf_name";
}
##
body file_select older_than(years, months, days, hours, minutes, seconds)
# Generic older_than selection body, aimed to have a common definition handy
# for every case possible.
{
mtime => irange(0,ago("$(years)","$(months)","$(days)","$(hours)","$(minutes)","$(seconds)"));
file_result => "mtime";
}
##
body file_select filetype_older_than(filetype, days)
# Select files of specified type older than specified number of days
# Note: This body only takes a single filetype, see filetypes_older_than
# if you want to select more than one type of file
{
file_types => { "$(filetype)" };
mtime => irange(0,ago(0,0,"$(days)",0,0,0));
file_result => "file_types.mtime";
}
##
body file_select filetypes_older_than(filetypes, days)
# Select files of specified type older than specified number of days
# Note: This body only takes a list of filetypes
{
file_types => { @(filetypes) };
mtime => irange(0,ago(0,0,"$(days)",0,0,0));
file_result => "file_types.mtime";
}
##-------------------------------------------------------
## changes
##-------------------------------------------------------
body changes detect_all_change
# This is fierce, and will cost disk cycles
{
hash => "best";
report_changes => "all";
update_hashes => "yes";
}
##
body changes detect_all_change_using(hash)
# Detect all changes using a configurable hashing algorithm
# for times when you care about both content and file stats e.g. mtime
# hash - supported hashing algorithm (md5, sha1, sha224, sha256, sha384,
# sha512, best)
{
hash => "$(hash)";
report_changes => "all";
update_hashes => "yes";
}
##
body changes detect_content
# This is a cheaper alternative
{
hash => "md5";
report_changes => "content";
update_hashes => "yes";
}
##
body changes detect_content_using(hash)
# Detect content changes using a configurable hashing algorithm
# for times when you only care about content, not file stats e.g. mtime
# hash - supported hashing algorithm (md5, sha1, sha224, sha256, sha384,
# sha512, best)
{
hash => "$(hash)";
report_changes => "content";
update_hashes => "yes";
}
##
body changes noupdate
# Use on (small) files that should never change
{
hash => "sha256";
report_changes => "content";
update_hashes => "no";
}
##
body changes diff
# Generates diff report (Nova and above)
{
hash => "sha256";
report_changes => "content";
report_diffs => "true";
update_hashes => "yes";
}
##
body changes all_changes
# Generates diff report (Nova and above)
{
hash => "sha256";
report_changes => "all";
report_diffs => "true";
update_hashes => "yes";
}
##
body changes diff_noupdate
{
hash => "sha256";
report_changes => "content";
report_diffs => "true";
update_hashes => "no";
}
##--------------------------------------------------------------
## Packages promises
##--------------------------------------------------------------
body package_method zypper
{
package_changes => "bulk";
package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\"";
# set it to "0" to avoid caching of list during upgrade
package_list_update_ifelapsed => "240";
package_patch_list_command => "/usr/bin/zypper patches";
package_installed_regex => "i.*";
package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*";
package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_patch_installed_regex => ".*Installed.*|.*Not Applicable.*";
package_patch_name_regex => "[^|]+\|\s+([^\s]+).*";
package_patch_version_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*";
package_name_convention => "$(name)";
package_add_command => "/usr/bin/zypper --non-interactive install";
package_delete_command => "/usr/bin/zypper --non-interactive remove --force-resolution";
package_update_command => "/usr/bin/zypper --non-interactive update";
package_patch_command => "/usr/bin/zypper --non-interactive patch$"; # $ means no args
package_verify_command => "/usr/bin/zypper --non-interactive verify$";
}
##
bundle common debian_knowledge
{
vars:
"apt_prefix" string => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C PATH=/bin:/sbin/:/usr/bin:/usr/sbin";
"call_dpkg" string => "$(apt_prefix) $(paths.path[dpkg])";
"call_apt_get" string => "$(apt_prefix) $(paths.path[apt_get])";
"call_aptitude" string => "$(apt_prefix) $(paths.path[aptitude])";
"dpkg_options" string => "-o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef";
}
body package_method apt
{
package_changes => "bulk";
package_list_command => "/usr/bin/dpkg -l";
package_list_name_regex => ".i\s+([^\s:]+).*";
package_list_version_regex => ".i\s+[^\s]+\s+([^\s]+).*";
package_installed_regex => ".i.*"; # packages that have been uninstalled may be listed
package_name_convention => "$(name)";
# set it to "0" to avoid caching of list during upgrade
package_list_update_ifelapsed => "240";
have_aptitude::
package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --assume-yes install";
package_list_update_command => "/usr/bin/aptitude update";
package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --assume-yes -q remove";
package_update_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --assume-yes install";
package_patch_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --assume-yes install";
package_verify_command => "/usr/bin/aptitude show";
package_noverify_regex => "(State: not installed|E: Unable to locate package .*)";
!have_aptitude::
package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --yes install";
package_list_update_command => "/usr/bin/apt-get update";
package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --yes -q remove";
package_update_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --yes install";
package_patch_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --yes install";
package_verify_command => "/usr/bin/dpkg -s";
package_noverify_returncode => "1";
}
##
body package_method dpkg_version(repo)
{
package_changes => "individual";
package_list_command => "/usr/bin/dpkg -l";
# set it to "0" to avoid caching of list during upgrade
package_list_update_ifelapsed => "240";
package_list_name_regex => ".i\s+([^\s:]+).*";
package_list_version_regex => ".i\s+[^\s]+\s+([^\s]+).*";
package_installed_regex => ".i.*"; # packages that have been uninstalled may be listed
package_file_repositories => { "$(repo)" };
debian.x86_64::
package_name_convention => "$(name)_$(version)_amd64.deb";
debian.i686::
package_name_convention => "$(name)_$(version)_i386.deb";
debian::
package_add_command => "/usr/bin/dpkg --install";
package_delete_command => "/usr/bin/dpkg --purge";
package_update_command => "/usr/bin/dpkg --install";
package_patch_command => "/usr/bin/dpkg --install";
}
##
body package_method rpm_version(repo)
{
package_changes => "individual";
package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\"";
# set it to "0" to avoid caching of list during upgrade
package_list_update_ifelapsed => "240";
package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s|]+).*";
package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s|]+).*";
package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_installed_regex => "i.*";
package_file_repositories => { "$(repo)" };
package_name_convention => "$(name)-$(version).$(arch).rpm";
package_add_command => "/bin/rpm -ivh ";
package_update_command => "/bin/rpm -Uvh ";
package_patch_command => "/bin/rpm -Uvh ";
package_delete_command => "/bin/rpm -e --nodeps";
package_noverify_regex => ".*[^\s].*";
}
##
body package_method windows_feature
{
package_changes => "individual";
package_name_convention => "$(name)";
package_delete_convention => "$(name)";
package_installed_regex => ".*";
package_list_name_regex => "(.*)";
package_list_version_regex => "(.*)"; # FIXME: the listing does not give version, so takes name for version too now
package_add_command => "$(sys.winsysdir)\WindowsPowerShell\v1.0\powershell.exe -Command \"Import-Module ServerManager; Add-WindowsFeature -Name\"";
package_delete_command => "$(sys.winsysdir)\WindowsPowerShell\v1.0\powershell.exe -Command \"Import-Module ServerManager; Remove-WindowsFeature -confirm:$false -Name\"";
package_list_command => "$(sys.winsysdir)\WindowsPowerShell\v1.0\powershell.exe -Command \"Import-Module ServerManager; Get-WindowsFeature | where {$_.installed -eq $True} |foreach {$_.Name}\"";
}
##
body package_method msi_implicit(repo)
# Use whole file name as promiser, e.g. "7-Zip-4.50-x86_64.msi",
# the name, version and arch is then deduced from the promiser
{
package_changes => "individual";
package_file_repositories => { "$(repo)" };
package_installed_regex => ".*";
package_name_convention => "$(name)-$(version)-$(arch).msi";
package_delete_convention => "$(firstrepo)$(name)-$(version)-$(arch).msi";
package_name_regex => "^(\S+)-(\d+\.?)+";
package_version_regex => "^\S+-((\d+\.?)+)";
package_arch_regex => "^\S+-[\d\.]+-(.*).msi";
package_add_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i";
package_update_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i";
package_delete_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /x";
}
##
body package_method msi_explicit(repo)
# use software name as promiser, e.g. "7-Zip", and explicitly
# specify any package_version and package_arch
{
package_changes => "individual";
package_file_repositories => { "$(repo)" };
package_installed_regex => ".*";
package_name_convention => "$(name)-$(version)-$(arch).msi";
package_delete_convention => "$(firstrepo)$(name)-$(version)-$(arch).msi";
package_add_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i";
package_update_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i";
package_delete_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /x";
}
##
body package_method yum
{
package_changes => "bulk";
package_list_command => "/usr/bin/yum list installed";
package_patch_list_command => "/usr/bin/yum check-update";
# Remember to escape special characters like |
package_list_name_regex => "([^.]+).*";
package_list_version_regex => "[^\s]\s+([^\s]+).*";
package_list_arch_regex => "[^.]+\.([^\s]+).*";
package_installed_regex => ".*(installed|\s+@).*";
package_name_convention => "$(name).$(arch)";
package_delete_convention => "${name}";
# set it to "0" to avoid caching of list during upgrade
package_list_update_ifelapsed => "240";
package_patch_installed_regex => "^[^*]\s.*";
package_patch_name_regex => "([^.]+).*";
package_patch_version_regex => "[^\s]\s+([^\s]+).*";
package_patch_arch_regex => "[^.]+\.([^\s]+).*";
package_add_command => "/usr/bin/yum -y install";
package_update_command => "/usr/bin/yum -y update";
package_patch_command => "/usr/bin/yum -y update";
package_delete_command => "/bin/rpm -e --nodeps";
package_verify_command => "/bin/rpm -V";
}
##
body package_method yum_rpm
# Contributed by Trond Hasle Amundsen
# More efficient package method for RedHat - uses rpm to list instead of yum
# Notes:
# - using $(name).$(arch) instead of $(name) for package_name_convention
# causes uninstallation to fail.
# - using allmatches to remove for all architectures
#
{
package_changes => "bulk";
package_list_command => "/bin/rpm -qa --qf '%{name} %{version}-%{release} %{arch}\n'";
package_patch_list_command => "/usr/bin/yum check-update";
package_list_name_regex => "^(\S+?)\s\S+?\s\S+$";
package_list_version_regex => "^\S+?\s(\S+?)\s\S+$";
package_list_arch_regex => "^\S+?\s\S+?\s(\S+)$";
package_installed_regex => ".*";
package_name_convention => "$(name)";
package_patch_installed_regex => "^[^*]\s.*";
package_patch_name_regex => "([^.]+).*";
package_patch_version_regex => "[^\s]\s+([^\s]+).*";
package_patch_arch_regex => "[^.]+\.([^\s]+).*";
package_add_command => "/usr/bin/yum -y install";
package_update_command => "/usr/bin/yum -y update";
package_patch_command => "/usr/bin/yum -y update";
package_delete_command => "/bin/rpm -e --nodeps --allmatches";
package_verify_command => "/bin/rpm -V";
}
##
body package_method yum_group
# Makes use of the "groups of packages" feature of Yum possible. (yum groupinstall, groupremove)
#
# Groups must be specified by their groupids, available through yum grouplist -v (between parentheses)
# $ yum grouplist -v|grep Networking|head -n 1
# Networking Tools (network-tools) <--- network-tools is the groupid
#
# Policies examples:
#
# -Install "web-server" group:
# ----------------------------
#
# packages:
# "web-server"
# package_policy => "add",
# package_method => yum_group;
#
# -Remove "debugging" and "php" groups:
# -------------------------------------
#
# vars:
# "groups" slist => { "debugging", "php" };
#
# packages:
# "$(groups)"
# package_policy => "delete",
# package_method => yum_group;
#
{
package_add_command => "/usr/bin/yum groupinstall -y";
package_changes => "bulk";
package_delete_command => "/usr/bin/yum groupremove -y";
package_delete_convention => "$(name)";
package_installed_regex => "^i.*";
# Generate a dpkg -l like listing, "i" means installed, "a" available, and a dummy version 1
package_list_command =>
"/usr/bin/yum grouplist -v|awk '$0 ~ /^Done$/ {next} {sub(/.*\(/, \"\");sub(/\).*/, \"\")} /Available/ {h=\"a\";next} /Installed/ {h=\"i\";next} h==\"i\" || h==\"a\" {print h\" \"$0\" 1\"}'";
package_list_name_regex => "a|i ([^\s]+) 1";
package_list_update_command => "/usr/bin/yum --quiet check-update";
package_list_update_ifelapsed => "240";
package_list_version_regex => "(1)";
package_name_convention => "$(name)";
package_name_regex => "(.*)";
package_noverify_returncode => "0";
package_update_command => "/usr/bin/yum groupupdate";
# grep -x to only get full line matching
package_verify_command => "/usr/bin/yum grouplist -v|awk '$0 ~ /^Done$/ {next} {sub(/.*\(/, \"\");sub(/\).*/, \"\")} /Available/ {h=\"a\";next} /Installed/ {h=\"i\";next} h==\"i\"|grep -qx";
}
##
body package_method rpm_filebased(path)
# Contributed by Aleksey Tsalolikhin. Written on 29-Feb-2012.
# Based on yum_rpm body in COPBL by Trond Hasle Amundsen.
# Purpose: install packages from local filesystem-based package repository.
# Note: Specify the path to the local package repository in the argument.
# Example of how to use it:
#
# {{{
# packages:
# "epel-release"
# package_policy => "add",
# package_version => "5-4",
# package_architectures => { "noarch" },
# package_method => rpm_filebased("/repo/RPMs");
# }}}
{
package_file_repositories => { "$(path)" };
# the above is an addition to Trond's yum_rpm body
package_add_command => "/bin/rpm -ihv ";
# The above is a change from Trond's yum_rpm body, this makes the commands rpm only.
# The reason I changed the install command from yum to rpm is yum will be default
# refuse to install the epel-release RPM as it does not have the EPEL GPG key,
# but rpm goes ahead and installs the epel-release RPM and the EPEL GPG key.
package_name_convention => "$(name)-$(version).$(arch).rpm";
# The above is a change from Tron's yum_rpm body. When package_file_repositories is in play,
# package_name_convention has to match the file name, not the package name, per the
# CFEngine 3 Reference Manual
# The rest is unchanged from Trond's yum_rpm body
package_changes => "bulk";
package_list_command => "/bin/rpm -qa --qf '%{name} %{version}-%{release} %{arch}\n'";
package_list_name_regex => "^(\S+?)\s\S+?\s\S+$";
package_list_version_regex => "^\S+?\s(\S+?)\s\S+$";
package_list_arch_regex => "^\S+?\s\S+?\s(\S+)$";
package_installed_regex => ".*";
package_delete_command => "/bin/rpm -e --allmatches";
package_verify_command => "/bin/rpm -V";
}
##
# OpenSolaris based systems (Solaris 11, Illumos, etc) use the much better
# Image Package System.
body package_method ips {
package_changes => "bulk";
package_list_command => "/usr/bin/pkg list -v --no-refresh";
package_list_name_regex => "pkg://.+?/([^\s]+)@.*$";
package_list_version_regex => "[^\s]+@([^\s]+).*";
package_installed_regex => ".*(i..)"; # all reported are installed
# set it to "0" to avoid caching of list during upgrade
package_list_update_ifelapsed => "240";
package_add_command => "/usr/bin/pkg install --accept ";
package_list_update_command => "/usr/bin/pkg refresh --full";
package_delete_command => "/usr/bin/pkg uninstall";
package_update_command => "/usr/bin/pkg install --accept";
package_patch_command => "/usr/bin/pkg install --accept";
package_verify_command => "/usr/bin/pkg list -a -v --no-refresh";
package_noverify_regex => "(.*---|pkg list: no packages matching .* installed)";
}
##
# SmartOS (solaris 10 fork by Joyent) uses pkgin
body package_method smartos
{
package_changes => "bulk";
package_list_command => "/opt/local/bin/pkgin list";
package_list_name_regex => "(.*)\-[0-9]+.*";
package_list_version_regex => ".*\-([0-9][^\s]+).*";
package_installed_regex => ".*"; # all reported are installed
package_list_update_command => "/opt/local/bin/pkgin -y update";
package_list_update_ifelapsed => "240";
package_add_command => "/opt/local/bin/pkgin -y install";
package_delete_command => "/opt/local/bin/pkgin -y remove";
package_update_command => "/opt/local/bin/pkgin upgrade";
}
# OpenCSW (Solaris software packages)
body package_method opencsw
{
package_changes => "bulk";
package_list_command => "/opt/csw/bin/pkgutil -c";
package_list_name_regex => "CSW(.*?)\s.*";
package_list_version_regex => ".*?\s+(.*),.*";
package_installed_regex => ".*"; # all reported are installed
package_list_update_command => "/opt/csw/bin/pkgutil -U";
package_list_update_ifelapsed => "240";
package_add_command => "/opt/csw/bin/pkgutil -yi";
package_delete_command => "/opt/csw/bin/pkgutil -yr";
package_update_command => "/opt/csw/bin/pkgutil -yu";
}
# The older solaris package system is poorly designed, with too many different
# names to track. See the example in tests/units/unit_package_solaris.cf
# to see how to use this
body package_method solaris (pkgname, spoolfile, adminfile)
{
package_changes => "individual";
package_list_command => "/usr/bin/pkginfo -l";
package_multiline_start => "\s*PKGINST:\s+[^\s]+.*";
package_list_name_regex => "\s*PKGINST:\s+([^\s]+).*";
package_list_version_regex => "\s*VERSION:\s+([^\s]+).*";
package_list_arch_regex => "\s*ARCH:\s+([^\s]+)";
package_installed_regex => "\s*STATUS:\s*(completely|partially)\s+installed.*";
package_name_convention => "$(name)";
package_add_command => "/usr/sbin/pkgadd -n -a /tmp/$(adminfile) -d /tmp/$(spoolfile)";
package_delete_command => "/usr/sbin/pkgrm -n -a /tmp/$(adminfile)";
}
##
#
# The following bundle is part of a package setup for solaris, see unit examples
#
bundle edit_line create_solaris_admin_file
{
insert_lines:
"mail=
instance=unique
partial=nocheck
runlevel=nocheck
idepend=nocheck
rdepend=nocheck
space=nocheck
setuid=nocheck
conflict=nocheck
action=nocheck
networktimeout=60
networkretries=3
authentication=quit
keystore=/var/sadm/security
proxy=
basedir=default"
comment => "Insert contents of Solaris admin file (automatically install packages)";
}
##
body package_method freebsd
{
package_changes => "individual";
# Could use rpm for this
package_list_command => "/usr/sbin/pkg_info";
# Remember to escape special characters like |
package_list_name_regex => "([^\s]+)-.*";
package_list_version_regex => "[^\s]+-([^\s]+).*";
package_name_regex => "([^\s]+)-.*";
package_version_regex => "[^\s]+-([^\s]+).*";
package_installed_regex => ".*";
package_name_convention => "$(name)-$(version)";
package_add_command => "/usr/sbin/pkg_add -r";
package_delete_command => "/usr/sbin/pkg_delete";
}
body package_method freebsd_portmaster
{
package_changes => "individual";
package_list_command => "/usr/sbin/pkg_info";
package_list_name_regex => "([^\s]+)-.*";
package_list_version_regex => "[^\s]+-([^\s]+).*";
package_installed_regex => ".*";
package_name_convention => "$(name)";
package_delete_convention => "$(name)-$(version)";
package_file_repositories => {
"/usr/ports/accessibility/",
"/usr/port/arabic/",
"/usr/ports/archivers/",
"/usr/ports/astro/",
"/usr/ports/audio/",
"/usr/ports/benchmarks/",
"/usr/ports/biology/",
"/usr/ports/cad/",
"/usr/ports/chinese/",
"/usr/ports/comms/",
"/usr/ports/converters/",
"/usr/ports/databases/",
"/usr/ports/deskutils/",
"/usr/ports/devel/",
"/usr/ports/dns/",
"/usr/ports/editors/",
"/usr/ports/emulators/",
"/usr/ports/finance/",
"/usr/ports/french/",
"/usr/ports/ftp/",
"/usr/ports/games/",
"/usr/ports/german/",
"/usr/ports/graphics/",
"/usr/ports/hebrew/",
"/usr/ports/hungarian/",
"/usr/ports/irc/",
"/usr/ports/japanese/",
"/usr/ports/java/",
"/usr/ports/korean/",
"/usr/ports/lang/",
"/usr/ports/mail/",
"/usr/ports/math/",
"/usr/ports/mbone/",
"/usr/ports/misc/",
"/usr/ports/multimedia/",
"/usr/ports/net/",
"/usr/ports/net-im/",
"/usr/ports/net-mgmt/",
"/usr/ports/net-p2p/",
"/usr/ports/news/",
"/usr/ports/packages/",
"/usr/ports/palm/",
"/usr/ports/polish/",
"/usr/ports/ports-mgmt/",
"/usr/ports/portuguese/",
"/usr/ports/print/",
"/usr/ports/russian/",
"/usr/ports/science/",
"/usr/ports/security/",
"/usr/ports/shells/",
"/usr/ports/sysutils/",
"/usr/ports/textproc/",
"/usr/ports/ukrainian/",
"/usr/ports/vietnamese/",
"/usr/ports/www/",
"/usr/ports/x11/",
"/usr/ports/x11-clocks/",
"/usr/ports/x11-drivers/",
"/usr/ports/x11-fm/",
"/usr/ports/x11-fonts/",
"/usr/ports/x11-servers/",
"/usr/ports/x11-themes/",
"/usr/ports/x11-toolkits/",
"/usr/ports/x11-wm/",
};
package_add_command => "/usr/local/sbin/portmaster -D -G --no-confirm";
package_update_command => "/usr/local/sbin/portmaster -D -G --no-confirm";
package_delete_command => "/usr/local/sbin/portmaster --no-confirm -e";
}
##
body package_method alpinelinux
{
package_changes => "bulk";
package_list_command => "/sbin/apk info -v";
package_list_name_regex => "([^\s]+)-.*";
package_list_version_regex => "[^\s]+-([^\s]+).*";
package_name_regex => ".*";
package_installed_regex => ".*";
package_name_convention => "$(name)";
package_add_command => "/sbin/apk add";
package_delete_command => "/sbin/apk del";
}
##
body package_method emerge
{
package_changes => "individual";
package_list_command => "/bin/sh -c '/bin/ls -d /var/db/pkg/*/* | cut -c 13-'";
package_list_name_regex => ".*/([^\s]+)-\d.*";
package_list_version_regex => ".*/[^\s]+-(\d.*)";
package_installed_regex => ".*"; # all reported are installed
package_name_convention => "$(name)";
package_list_update_command => "/bin/true"; # I prefer manual syncing
#package_list_update_command => "/usr/bin/emerge --sync"; # if you like automatic
package_list_update_ifelapsed => "240"; # should happen every 4 hours
package_add_command => "/usr/bin/emerge -q --quiet-build";
package_delete_command => "/usr/bin/emerge --depclean";
package_update_command => "/usr/bin/emerge --update";
package_patch_command => "/usr/bin/emerge --update";
package_verify_command => "/usr/bin/emerge -s";
package_noverify_regex => ".*(Not Installed|Applications found : 0).*";
}
##
body package_method pacman
{
package_changes => "bulk";
package_list_command => "/usr/bin/pacman -Q";
# set it to "0" to avoid caching of list during upgrade
package_list_update_ifelapsed => "240";
package_list_name_regex => "(.*)\s+.*";
package_list_version_regex => ".*\s+(.*)";
package_installed_regex => ".*";
package_name_convention => "$(name)";
package_add_command => "/usr/bin/pacman -S --noconfirm --noprogressbar --needed";
package_delete_command => "/usr/bin/pacman -Rs --noconfirm";
package_update_command => "/usr/bin/pacman -S --noconfirm --noprogressbar --needed";
}
##
# Single bundle for all the similar managers simplifies promises
body package_method generic
{
SuSE::
package_changes => "bulk";
package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\"";
package_patch_list_command => "/usr/bin/zypper patches";
package_installed_regex => "i.*";
package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*";
package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
package_patch_installed_regex => ".*Installed.*|.*Not Applicable.*";
package_patch_name_regex => "[^|]+\|\s+([^\s]+).*";
package_patch_version_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*";
package_name_convention => "$(name)";
package_add_command => "/usr/bin/zypper --non-interactive install";
package_delete_command => "/usr/bin/zypper --non-interactive remove --force-resolution";
package_update_command => "/usr/bin/zypper --non-interactive update";
package_patch_command => "/usr/bin/zypper --non-interactive patch$"; # $ means no args
package_verify_command => "/usr/bin/zypper --non-interactive verify$";
redhat::
package_changes => "bulk";
package_list_command => "/bin/rpm -qa --qf '%{name} %{version}-%{release} %{arch}\n'";
package_patch_list_command => "/usr/bin/yum check-update";
package_list_name_regex => "^(\S+?)\s\S+?\s\S+$";
package_list_version_regex => "^\S+?\s(\S+?)\s\S+$";
package_list_arch_regex => "^\S+?\s\S+?\s(\S+)$";
package_installed_regex => ".*";
package_name_convention => "$(name)";
package_list_update_ifelapsed => "0"; # sometimes, caching is pretty disturbing
package_patch_installed_regex => "^[^*]\s.*";
package_patch_name_regex => "([^.]+).*";
package_patch_version_regex => "[^\s]\s+([^\s]+).*";
package_patch_arch_regex => "[^.]+\.([^\s]+).*";
package_add_command => "/usr/bin/yum -y install";
package_update_command => "/usr/bin/yum -y update";
package_patch_command => "/usr/bin/yum -y update";
package_delete_command => "/bin/rpm -e --nodeps --allmatches";
package_verify_command => "/bin/rpm -V";
# package_changes => "bulk";
# package_list_command => "/usr/bin/yum list installed";
# package_patch_list_command => "/usr/bin/yum check-update";
# package_list_name_regex => "([^.]+).*";
# package_list_version_regex => "[^\s]\s+([^\s]+).*";
# package_list_arch_regex => "[^.]+\.([^\s]+).*";
# package_installed_regex => ".*(installed|\s+@).*";
# package_name_convention => "$(name).$(arch)";
# package_list_update_ifelapsed => "240";
# package_patch_installed_regex => "^[^*]\s.*";
# package_patch_name_regex => "([^.]+).*";
# package_patch_version_regex => "[^\s]\s+([^\s]+).*";
# package_patch_arch_regex => "[^.]+\.([^\s]+).*";
# package_add_command => "/usr/bin/yum -y install";
# package_delete_command => "/bin/rpm -e --nodeps";
# package_verify_command => "/bin/rpm -V";
debian::
package_changes => "bulk";
package_list_command => "/usr/bin/dpkg -l";
package_list_name_regex => ".i\s+([^\s:]+).*";
package_list_version_regex => ".i\s+[^\s]+\s+([^\s]+).*";
package_installed_regex => ".i.*"; # packages that have been uninstalled may be listed
package_name_convention => "$(name)";
package_list_update_ifelapsed => "240"; # 4 hours
debian.have_aptitude::
package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --assume-yes install";
package_list_update_command => "/usr/bin/aptitude update";
package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --assume-yes remove";
package_update_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --assume-yes install";
package_patch_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --assume-yes install";
package_verify_command => "/usr/bin/aptitude show";
package_noverify_regex => "(State: not installed|E: Unable to locate package .*)";
debian.!have_aptitude::
package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --yes install";
package_list_update_command => "/usr/bin/apt-get update";
package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --yes remove";
package_update_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --yes install";
package_patch_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --yes install";
package_verify_command => "/usr/bin/dpkg -s";
package_noverify_returncode => "1";
freebsd::
package_changes => "individual";
package_list_command => "/usr/sbin/pkg_info";
package_list_name_regex => "([^\s]+)-.*";
package_list_version_regex => "[^\s]+-([^\s]+).*";
package_name_regex => "([^\s]+)-.*";
package_version_regex => "[^\s]+-([^\s]+).*";
package_installed_regex => ".*";
package_name_convention => "$(name)-$(version)";
package_add_command => "/usr/sbin/pkg_add -r";
package_delete_command => "/usr/sbin/pkg_delete";
gentoo::
package_changes => "individual";
package_list_command => "/bin/sh -c '/bin/ls -d /var/db/pkg/*/* | cut -c 13-'";
package_list_name_regex => ".*/([^\s]+)-\d.*";
package_list_version_regex => ".*/[^\s]+-(\d.*)";
package_installed_regex => ".*"; # all reported are installed
package_name_convention => "$(name)";
package_list_update_command => "/bin/true"; # I prefer manual syncing
#package_list_update_command => "/usr/bin/emerge --sync"; # if you like automatic
package_list_update_ifelapsed => "240"; # should happen every 4 hours
package_add_command => "/usr/bin/emerge -q --quiet-build";
package_delete_command => "/usr/bin/emerge --depclean";
package_update_command => "/usr/bin/emerge --update";
package_patch_command => "/usr/bin/emerge --update";
package_verify_command => "/usr/bin/emerge -s";
package_noverify_regex => ".*(Not Installed|Applications found : 0).*";
}
##
##-------------------------------------------------------
## storage promises
##-------------------------------------------------------
body volume min_free_space(free)
{
check_foreign => "false";
freespace => "$(free)";
sensible_size => "10000";
sensible_count => "2";
}
##
body mount nfs(server,source)
{
mount_type => "nfs";
mount_source => "$(source)";
mount_server => "$(server)";
edit_fstab => "true";
}
##
body mount nfs_p(server,source,perm)
{
mount_type => "nfs";
mount_source => "$(source)";
mount_server => "$(server)";
mount_options => {"$(perm)"};
edit_fstab => "true";
}
##
body mount unmount
{
mount_type => "nfs";
edit_fstab => "true";
unmount => "true";
}
##-------------------------------------------------------
## process promises
##-------------------------------------------------------
body process_select exclude_procs(x)
{
command => "$(x)";
process_result => "!command";
}
##
body process_select days_older_than(d)
{
stime_range => irange(ago(0,0,"$(d)",0,0,0),now);
process_result => "stime";
}
##
body process_count any_count(cl)
{
match_range => "0,0";
out_of_range_define => { "$(cl)" };
}
##
body process_count check_range(name,lower,upper)
{
match_range => irange("$(lower)","$(upper)");
out_of_range_define => { "$(name)_out_of_range" };
}
##-------------------------------------------------------
## service promises
##-------------------------------------------------------
body service_method bootstart
{
service_autostart_policy => "boot_time";
service_dependence_chain => "start_parent_services";
windows::
service_type => "windows";
}
##
body service_method force_deps
{
service_dependence_chain => "all_related";
windows::
service_type => "windows";
}
##
bundle agent standard_services(service,state)
{
# DATA,
vars:
any::
"stakeholders[cfengine3]" slist => { "cfengine_in" };
"stakeholders[acpid]" slist => { "cpu", "cpu0", "cpu1", "cpu2", "cpu3" };
"stakeholders[mongod]" slist => { "mongo_in" };
"stakeholders[postfix]" slist => { "smtp_in" };
"stakeholders[sendmail]" slist => { "smtp_in" };
"stakeholders[www]" slist => { "www_in", "wwws_in", "www_alt_in" };
"stakeholders[ssh]" slist => { "ssh_in" };
"stakeholders[mysql]" slist => { "mysql_in" };
"stakeholders[nfs]" slist => { "nfsd_in" };
"stakeholders[syslog]" slist => { "syslog" };
"stakeholders[rsyslog]" slist => { "syslog" };
"stakeholders[tomcat5]" slist => { "www_alt_in" };
"stakeholders[tomcat6]" slist => { "www_alt_in" };
linux::
"startcommand[acpid]" string => "/etc/init.d/acpid start";
"restartcommand[acpid]" string => "/etc/init.d/acpid restart";
"reloadcommand[acpid]" string => "/etc/init.d/acpid reload";
"stopcommand[acpid]" string => "/etc/init.d/acpid stop";
"pattern[acpid]" string => ".*acpid.*";
"startcommand[cfengine3]" string => "/etc/init.d/cfengine3 start";
"restartcommand[cfengine3]" string => "/etc/init.d/cfengine3 restart";
"reloadcommand[cfengine3]" string => "/etc/init.d/cfengine3 reload";
"stopcommand[cfengine3]" string => "/etc/init.d/cfengine3 stop";
"pattern[cfengine3]" string => ".*cf-execd.*";
"startcommand[fancontrol]" string => "/etc/init.d/fancontrol start";
"restartcommand[fancontrol]" string => "/etc/init.d/fancontrol restart";
"reloadcommand[fancontrol]" string => "/etc/init.d/fancontrol reload";
"stopcommand[fancontrol]" string => "/etc/init.d/fancontrol stop";
"pattern[fancontrol]" string => ".*fancontrol.*";
"startcommand[hddtemp]" string => "/etc/init.d/hddtemp start";
"restartcommand[hddtemp]" string => "/etc/init.d/hddtemp restart";
"reloadcommand[hddtemp]" string => "/etc/init.d/hddtemp reload";
"stopcommand[hddtemp]" string => "/etc/init.d/hddtemp stop";
"pattern[hddtemp]" string => ".*hddtemp.*";
"startcommand[irqbalance]" string => "/etc/init.d/irqbalance start";
"restartcommand[irqbalance]" string => "/etc/init.d/irqbalance restart";
"reloadcommand[irqbalance]" string => "/etc/init.d/irqbalance reload";
"stopcommand[irqbalance]" string => "/etc/init.d/irqbalance stop";
"pattern[irqbalance]" string => ".*irqbalance.*";
"startcommand[lm-sensor]" string => "/etc/init.d/lm-sensor start";
"restartcommand[lm-sensor]" string => "/etc/init.d/lm-sensor restart";
"reloadcommand[lm-sensor]" string => "/etc/init.d/lm-sensor reload";
"stopcommand[lm-sensor]" string => "/etc/init.d/lm-sensor stop";
"pattern[lm-sensor]" string => ".*psensor.*";
"startcommand[mongod]" string => "/etc/init.d/mongod start";
"restartcommand[mongod]" string => "/etc/init.d/mongod restart";
"reloadcommand[mongod]" string => "/etc/init.d/mongod reload";
"stopcommand[mongod]" string => "/etc/init.d/mongod stop";
"pattern[mongod]" string => ".*mongod.*";
"startcommand[openvpn]" string => "/etc/init.d/openvpn start";
"restartcommand[openvpn]" string => "/etc/init.d/openvpn restart";
"reloadcommand[openvpn]" string => "/etc/init.d/openvpn reload";
"stopcommand[openvpn]" string => "/etc/init.d/openvpn stop";
"pattern[openvpn]" string => ".*openvpn.*";
"startcommand[postfix]" string => "/etc/init.d/postfix start";
"restartcommand[postfix]" string => "/etc/init.d/postfix restart";
"reloadcommand[postfix]" string => "/etc/init.d/postfix reload";
"stopcommand[postfix]" string => "/etc/init.d/postfix stop";
"pattern[postfix]" string => ".*postfix.*";
"startcommand[rsync]" string => "/etc/init.d/rsync start";
"restartcommand[rsync]" string => "/etc/init.d/rsync restart";
"reloadcommand[rsync]" string => "/etc/init.d/rsync reload";
"stopcommand[rsync]" string => "/etc/init.d/rsync stop";
"pattern[rsync]" string => ".*rsync.*";
"startcommand[rsyslog]" string => "/etc/init.d/rsyslog start";
"restartcommand[rsyslog]" string => "/etc/init.d/rsyslog restart";
"reloadcommand[rsyslog]" string => "/etc/init.d/rsyslog reload";
"stopcommand[rsyslog]" string => "/etc/init.d/rsyslog stop";
"pattern[rsyslog]" string => ".*rsyslogd.*";
"startcommand[sendmail]" string => "/etc/init.d/sendmail start";
"restartcommand[sendmail]" string => "/etc/init.d/sendmail restart";
"reloadcommand[sendmail]" string => "/etc/init.d/sendmail reload";
"stopcommand[sendmail]" string => "/etc/init.d/sendmail stop";
"pattern[sendmail]" string => ".*sendmail.*";
"startcommand[tomcat5]" string => "/etc/init.d/tomcat5 start";
"restartcommand[tomcat5]" string => "/etc/init.d/tomcat5 restart";
"reloadcommand[tomcat5]" string => "/etc/init.d/tomcat5 reload";
"stopcommand[tomcat5]" string => "/etc/init.d/tomcat5 stop";
"pattern[tomcat5]" string => ".*tomcat5.*";
"startcommand[tomcat6]" string => "/etc/init.d/tomcat6 start";
"restartcommand[tomcat6]" string => "/etc/init.d/tomcat6 restart";
"reloadcommand[tomcat6]" string => "/etc/init.d/tomcat6 reload";
"stopcommand[tomcat6]" string => "/etc/init.d/tomcat6 stop";
"pattern[tomcat6]" string => ".*tomcat6.*";
"startcommand[varnish]" string => "/etc/init.d/varnish start";
"restartcommand[varnish]" string => "/etc/init.d/varnish restart";
"reloadcommand[varnish]" string => "/etc/init.d/varnish reload";
"stopcommand[varnish]" string => "/etc/init.d/varnish stop";
"pattern[varnish]" string => ".*varnish.*";
"startcommand[wpa_supplicant]" string => "/etc/init.d/wpa_supplicant start";
"restartcommand[wpa_supplicant]" string => "/etc/init.d/wpa_supplicant restart";
"reloadcommand[wpa_supplicant]" string => "/etc/init.d/wpa_supplicant reload";
"stopcommand[wpa_supplicant]" string => "/etc/init.d/wpa_supplicant stop";
"pattern[wpa_supplicant]" string => ".*wpa_supplicant.*";
SuSE|suse::
"startcommand[mysql]" string => "/etc/init.d/mysqld start";
"restartcommand[mysql]" string => "/etc/init.d/mysqld restart";
"reloadcommand[mysql]" string => "/etc/init.d/mysqld reload";
"stopcommand[mysql]" string => "/etc/init.d/mysqld stop";
"pattern[mysql]" string => ".*mysqld.*";
"startcommand[www]" string => "/etc/init.d/apache2 start";
"restartcommand[www]" string => "/etc/init.d/apache2 restart";
"reloadcommand[www]" string => "/etc/init.d/apache2 reload";
"stopcommand[www]" string => "/etc/init.d/apache2 stop";
"pattern[www]" string => ".*apache2.*";
"startcommand[ssh]" string => "/etc/init.d/sshd start";
"restartcommand[ssh]" string => "/etc/init.d/sshd restart";
"reloadcommand[ssh]" string => "/etc/init.d/sshd reload";
"stopcommand[ssh]" string => "/etc/init.d/sshd stop";
"pattern[ssh]" string => ".*sshd.*";
redhat::
"startcommand[anacron]" string => "/etc/init.d/anacron start";
"restartcommand[anacron]" string => "/etc/init.d/anacron restart";
"reloadcommand[anacron]" string => "/etc/init.d/anacron reload";
"stopcommand[anacron]" string => "/etc/init.d/anacron stop";
"pattern[anacron]" string => ".*anacron.*";
"startcommand[atd]" string => "/etc/init.d/atd start";
"restartcommand[atd]" string => "/etc/init.d/atd restart";
"reloadcommand[atd]" string => "/etc/init.d/atd reload";
"stopcommand[atd]" string => "/etc/init.d/atd stop";
"pattern[atd]" string => ".*sbin/atd.*";
"startcommand[auditd]" string => "/etc/init.d/auditd start";
"restartcommand[auditd]" string => "/etc/init.d/auditd restart";
"reloadcommand[auditd]" string => "/etc/init.d/auditd reload";
"stopcommand[auditd]" string => "/etc/init.d/auditd stop";
"pattern[auditd]" string => ".*auditd$";
"startcommand[autofs]" string => "/etc/init.d/autofs start";
"restartcommand[autofs]" string => "/etc/init.d/autofs restart";
"reloadcommand[autofs]" string => "/etc/init.d/autofs reload";
"stopcommand[autofs]" string => "/etc/init.d/autofs stop";
"pattern[autofs]" string => ".*automount.*";
"startcommand[bluetoothd]" string => "/etc/init.d/bluetooth start";
"restartcommand[bluetoothd]" string => "/etc/init.d/bluetooth restart";
"reloadcommand[bluetoothd]" string => "/etc/init.d/bluetooth reload";
"stopcommand[bluetoothd]" string => "/etc/init.d/bluetooth stop";
"pattern[bluetoothd]" string => ".*hcid.*";
"startcommand[capi]" string => "/etc/init.d/capi start";
"restartcommand[capi]" string => "/etc/init.d/capi restart";
"reloadcommand[capi]" string => "/etc/init.d/capi reload";
"stopcommand[capi]" string => "/etc/init.d/capi stop";
"pattern[capi]" string => ".*capiinit.*";
"startcommand[conman]" string => "/etc/init.d/conman start";
"restartcommand[conman]" string => "/etc/init.d/conman restart";
"reloadcommand[conman]" string => "/etc/init.d/conman reload";
"stopcommand[conman]" string => "/etc/init.d/conman stop";
"pattern[conman]" string => ".*conmand.*";
"startcommand[cpuspeed]" string => "/etc/init.d/cpuspeed start";
"restartcommand[cpuspeed]" string => "/etc/init.d/cpuspeed restart";
"reloadcommand[cpuspeed]" string => "/etc/init.d/cpuspeed reload";
"stopcommand[cpuspeed]" string => "/etc/init.d/cpuspeed stop";
"pattern[cpuspeed]" string => ".*cpuspeed.*";
"startcommand[crond]" string => "/etc/init.d/crond start";
"restartcommand[crond]" string => "/etc/init.d/crond restart";
"reloadcommand[crond]" string => "/etc/init.d/crond reload";
"stopcommand[crond]" string => "/etc/init.d/crond stop";
"pattern[crond]" string => ".*crond.*";
"startcommand[dc_client]" string => "/etc/init.d/dc_client start";
"restartcommand[dc_client]" string => "/etc/init.d/dc_client restart";
"reloadcommand[dc_client]" string => "/etc/init.d/dc_client reload";
"stopcommand[dc_client]" string => "/etc/init.d/dc_client stop";
"pattern[dc_client]" string => ".*dc_client.*";
"startcommand[dc_server]" string => "/etc/init.d/dc_server start";
"restartcommand[dc_server]" string => "/etc/init.d/dc_server restart";
"reloadcommand[dc_server]" string => "/etc/init.d/dc_server reload";
"stopcommand[dc_server]" string => "/etc/init.d/dc_server stop";
"pattern[dc_server]" string => ".*dc_server.*";
"startcommand[dnsmasq]" string => "/etc/init.d/dnsmasq start";
"restartcommand[dnsmasq]" string => "/etc/init.d/dnsmasq restart";
"reloadcommand[dnsmasq]" string => "/etc/init.d/dnsmasq reload";
"stopcommand[dnsmasq]" string => "/etc/init.d/dnsmasq stop";
"pattern[dnsmasq]" string => ".*dnsmasq.*";
"startcommand[dund]" string => "/etc/init.d/dund start";
"restartcommand[dund]" string => "/etc/init.d/dund restart";
"reloadcommand[dund]" string => "/etc/init.d/dund reload";
"stopcommand[dund]" string => "/etc/init.d/dund stop";
"pattern[dund]" string => ".*dund.*";
"startcommand[gpm]" string => "/etc/init.d/gpm start";
"restartcommand[gpm]" string => "/etc/init.d/gpm restart";
"reloadcommand[gpm]" string => "/etc/init.d/gpm reload";
"stopcommand[gpm]" string => "/etc/init.d/gpm stop";
"pattern[gpm]" string => ".*gpm.*";
"startcommand[haldaemon]" string => "/etc/init.d/haldaemon start";
"restartcommand[haldaemon]" string => "/etc/init.d/haldaemon restart";
"reloadcommand[haldaemon]" string => "/etc/init.d/haldaemon reload";
"stopcommand[haldaemon]" string => "/etc/init.d/haldaemon stop";
"pattern[haldaemon]" string => ".*hald.*";
"startcommand[hidd]" string => "/etc/init.d/hidd start";
"restartcommand[hidd]" string => "/etc/init.d/hidd restart";
"reloadcommand[hidd]" string => "/etc/init.d/hidd reload";
"stopcommand[hidd]" string => "/etc/init.d/hidd stop";
"pattern[hidd]" string => ".*hidd.*";
# "startcommand[ip6tables]" string => "/etc/init.d/ip6tables start";
# "restartcommand[ip6tables]" string => "/etc/init.d/ip6tables restart";
# "reloadcommand[ip6tables]" string => "/etc/init.d/ip6tables reload";
# "stopcommand[ip6tables]" string => "/etc/init.d/ip6tables stop";
# "pattern[ip6tables]" string => ".*ip6tables.*";
# "startcommand[iptables]" string => "/etc/init.d/iptables start";
# "restartcommand[iptables]" string => "/etc/init.d/iptables restart";
# "reloadcommand[iptables]" string => "/etc/init.d/iptables reload";
# "stopcommand[iptables]" string => "/etc/init.d/iptables stop";
# "pattern[iptables]" string => ".*iptables.*";
"startcommand[irda]" string => "/etc/init.d/irda start";
"restartcommand[irda]" string => "/etc/init.d/irda restart";
"reloadcommand[irda]" string => "/etc/init.d/irda reload";
"stopcommand[irda]" string => "/etc/init.d/irda stop";
"pattern[irda]" string => ".*irattach.*";
"startcommand[iscsid]" string => "/etc/init.d/iscsid start";
"restartcommand[iscsid]" string => "/etc/init.d/iscsid restart";
"reloadcommand[iscsid]" string => "/etc/init.d/iscsid reload";
"stopcommand[iscsid]" string => "/etc/init.d/iscsid stop";
"pattern[iscsid]" string => ".*iscsid.*";
"startcommand[isdn]" string => "/etc/init.d/isdn start";
"restartcommand[isdn]" string => "/etc/init.d/isdn restart";
"reloadcommand[isdn]" string => "/etc/init.d/isdn reload";
"stopcommand[isdn]" string => "/etc/init.d/isdn stop";
"pattern[isdn]" string => ".*isdnlog.*";
"startcommand[lvm2-monitor]" string => "/etc/init.d/lvm2-monitor start";
"restartcommand[lvm2-monitor]" string => "/etc/init.d/lvm2-monitor restart";
"reloadcommand[lvm2-monitor]" string => "/etc/init.d/lvm2-monitor reload";
"stopcommand[lvm2-monitor]" string => "/etc/init.d/lvm2-monitor stop";
"pattern[lvm2-monitor]" string => ".*vgchange.*";
"startcommand[mcstrans]" string => "/etc/init.d/mcstrans start";
"restartcommand[mcstrans]" string => "/etc/init.d/mcstrans restart";
"reloadcommand[mcstrans]" string => "/etc/init.d/mcstrans reload";
"stopcommand[mcstrans]" string => "/etc/init.d/mcstrans stop";
"pattern[mcstrans]" string => ".*mcstransd.*";
"startcommand[mdmonitor]" string => "/etc/init.d/mdmonitor start";
"restartcommand[mdmonitor]" string => "/etc/init.d/mdmonitor restart";
"reloadcommand[mdmonitor]" string => "/etc/init.d/mdmonitor reload";
"stopcommand[mdmonitor]" string => "/etc/init.d/mdmonitor stop";
"pattern[mdmonitor]" string => ".*mdadm.*";
"startcommand[mdmpd]" string => "/etc/init.d/mdmpd start";
"restartcommand[mdmpd]" string => "/etc/init.d/mdmpd restart";
"reloadcommand[mdmpd]" string => "/etc/init.d/mdmpd reload";
"stopcommand[mdmpd]" string => "/etc/init.d/mdmpd stop";
"pattern[mdmpd]" string => ".*mdmpd.*";
"startcommand[messagebus]" string => "/etc/init.d/messagebus start";
"restartcommand[messagebus]" string => "/etc/init.d/messagebus restart";
"reloadcommand[messagebus]" string => "/etc/init.d/messagebus reload";
"stopcommand[messagebus]" string => "/etc/init.d/messagebus stop";
"pattern[messagebus]" string => ".*dbus-daemon.*";
"startcommand[microcode_ctl]" string => "/etc/init.d/microcode_ctl start";
"restartcommand[microcode_ctl]" string => "/etc/init.d/microcode_ctl restart";
"reloadcommand[microcode_ctl]" string => "/etc/init.d/microcode_ctl reload";
"stopcommand[microcode_ctl]" string => "/etc/init.d/microcode_ctl stop";
"pattern[microcode_ctl]" string => ".*microcode_ctl.*";
"startcommand[multipathd]" string => "/etc/init.d/multipathd start";
"restartcommand[multipathd]" string => "/etc/init.d/multipathd restart";
"reloadcommand[multipathd]" string => "/etc/init.d/multipathd reload";
"stopcommand[multipathd]" string => "/etc/init.d/multipathd stop";
"pattern[multipathd]" string => ".*multipathd.*";
"startcommand[mysql]" string => "/etc/init.d/mysqld start";
"restartcommand[mysql]" string => "/etc/init.d/mysqld restart";
"reloadcommand[mysql]" string => "/etc/init.d/mysqld reload";
"stopcommand[mysql]" string => "/etc/init.d/mysqld stop";
"pattern[mysql]" string => ".*mysqld.*";
"startcommand[netplugd]" string => "/etc/init.d/netplugd start";
"restartcommand[netplugd]" string => "/etc/init.d/netplugd restart";
"reloadcommand[netplugd]" string => "/etc/init.d/netplugd reload";
"stopcommand[netplugd]" string => "/etc/init.d/netplugd stop";
"pattern[netplugd]" string => ".*netplugd.*";
"startcommand[NetworkManager]" string => "/etc/init.d/NetworkManager start";
"restartcommand[NetworkManager]" string => "/etc/init.d/NetworkManager restart";
"reloadcommand[NetworkManager]" string => "/etc/init.d/NetworkManager reload";
"stopcommand[NetworkManager]" string => "/etc/init.d/NetworkManager stop";
"pattern[NetworkManager]" string => ".*NetworkManager.*";
"startcommand[nfs]" string => "/etc/init.d/nfs start";
"restartcommand[nfs]" string => "/etc/init.d/nfs restart";
"reloadcommand[nfs]" string => "/etc/init.d/nfs reload";
"stopcommand[nfs]" string => "/etc/init.d/nfs stop";
"pattern[nfs]" string => ".*nfsd.*";
"startcommand[nfslock]" string => "/etc/init.d/nfslock start";
"restartcommand[nfslock]" string => "/etc/init.d/nfslock restart";
"reloadcommand[nfslock]" string => "/etc/init.d/nfslock reload";
"stopcommand[nfslock]" string => "/etc/init.d/nfslock stop";
"pattern[nfslock]" string => ".*rpc.statd.*";
"startcommand[nscd]" string => "/etc/init.d/nscd start";
"restartcommand[nscd]" string => "/etc/init.d/nscd restart";
"reloadcommand[nscd]" string => "/etc/init.d/nscd reload";
"stopcommand[nscd]" string => "/etc/init.d/nscd stop";
"pattern[nscd]" string => ".*nscd.*";
"startcommand[oddjobd]" string => "/etc/init.d/oddjobd start";
"restartcommand[oddjobd]" string => "/etc/init.d/oddjobd restart";
"reloadcommand[oddjobd]" string => "/etc/init.d/oddjobd reload";
"stopcommand[oddjobd]" string => "/etc/init.d/oddjobd stop";
"pattern[oddjobd]" string => ".*oddjobd.*";
"startcommand[pand]" string => "/etc/init.d/pand start";
"restartcommand[pand]" string => "/etc/init.d/pand restart";
"reloadcommand[pand]" string => "/etc/init.d/pand reload";
"stopcommand[pand]" string => "/etc/init.d/pand stop";
"pattern[pand]" string => ".*pand.*";
"startcommand[pcscd]" string => "/etc/init.d/pcscd start";
"restartcommand[pcscd]" string => "/etc/init.d/pcscd restart";
"reloadcommand[pcscd]" string => "/etc/init.d/pcscd reload";
"stopcommand[pcscd]" string => "/etc/init.d/pcscd stop";
"pattern[pcscd]" string => ".*pcscd.*";
"startcommand[portmap]" string => "/etc/init.d/portmap start";
"restartcommand[portmap]" string => "/etc/init.d/portmap restart";
"reloadcommand[portmap]" string => "/etc/init.d/portmap reload";
"stopcommand[portmap]" string => "/etc/init.d/portmap stop";
"pattern[portmap]" string => ".*portmap.*";
"startcommand[postgresql]" string => "/etc/init.d/postgresql start";
"restartcommand[postgresql]" string => "/etc/init.d/postgresql restart";
"reloadcommand[postgresql]" string => "/etc/init.d/postgresql reload";
"stopcommand[postgresql]" string => "/etc/init.d/postgresql stop";
"pattern[postgresql]" string => ".*postmaster.*";
"startcommand[rdisc]" string => "/etc/init.d/rdisc start";
"restartcommand[rdisc]" string => "/etc/init.d/rdisc restart";
"reloadcommand[rdisc]" string => "/etc/init.d/rdisc reload";
"stopcommand[rdisc]" string => "/etc/init.d/rdisc stop";
"pattern[rdisc]" string => ".*rdisc.*";
"startcommand[rdisc]" string => "/etc/init.d/rdisc start";
"restartcommand[rdisc]" string => "/etc/init.d/rdisc restart";
"reloadcommand[rdisc]" string => "/etc/init.d/rdisc reload";
"stopcommand[rdisc]" string => "/etc/init.d/rdisc stop";
"pattern[rdisc]" string => ".*rdisc.*";
"startcommand[readahead_early]" string => "/etc/init.d/readahead_early start";
"restartcommand[readahead_early]" string => "/etc/init.d/readahead_early restart";
"reloadcommand[readahead_early]" string => "/etc/init.d/readahead_early reload";
"stopcommand[readahead_early]" string => "/etc/init.d/readahead_early stop";
"pattern[readahead_early]" string => ".*readahead.*early.*";
"startcommand[readahead_later]" string => "/etc/init.d/readahead_later start";
"restartcommand[readahead_later]" string => "/etc/init.d/readahead_later restart";
"reloadcommand[readahead_later]" string => "/etc/init.d/readahead_later reload";
"stopcommand[readahead_later]" string => "/etc/init.d/readahead_later stop";
"pattern[readahead_later]" string => ".*readahead.*later.*";
"startcommand[restorecond]" string => "/etc/init.d/restorecond start";
"restartcommand[restorecond]" string => "/etc/init.d/restorecond restart";
"reloadcommand[restorecond]" string => "/etc/init.d/restorecond reload";
"stopcommand[restorecond]" string => "/etc/init.d/restorecond stop";
"pattern[restorecond]" string => ".*restorecond.*";
"startcommand[rpcgssd]" string => "/etc/init.d/rpcgssd start";
"restartcommand[rpcgssd]" string => "/etc/init.d/rpcgssd restart";
"reloadcommand[rpcgssd]" string => "/etc/init.d/rpcgssd reload";
"stopcommand[rpcgssd]" string => "/etc/init.d/rpcgssd stop";
"pattern[rpcgssd]" string => ".*rpc.gssd.*";
"startcommand[rpcidmapd]" string => "/etc/init.d/rpcidmapd start";
"restartcommand[rpcidmapd]" string => "/etc/init.d/rpcidmapd restart";
"reloadcommand[rpcidmapd]" string => "/etc/init.d/rpcidmapd reload";
"stopcommand[rpcidmapd]" string => "/etc/init.d/rpcidmapd stop";
"pattern[rpcidmapd]" string => ".*rpc.idmapd.*";
"startcommand[rpcsvcgssd]" string => "/etc/init.d/rpcsvcgssd start";
"restartcommand[rpcsvcgssd]" string => "/etc/init.d/rpcsvcgssd restart";
"reloadcommand[rpcsvcgssd]" string => "/etc/init.d/rpcsvcgssd reload";
"stopcommand[rpcsvcgssd]" string => "/etc/init.d/rpcsvcgssd stop";
"pattern[rpcsvcgssd]" string => ".*rpc.svcgssd.*";
"startcommand[saslauthd]" string => "/etc/init.d/saslauthd start";
"restartcommand[saslauthd]" string => "/etc/init.d/saslauthd restart";
"reloadcommand[saslauthd]" string => "/etc/init.d/saslauthd reload";
"stopcommand[saslauthd]" string => "/etc/init.d/saslauthd stop";
"pattern[saslauthd]" string => ".*saslauthd.*";
"startcommand[smartd]" string => "/etc/init.d/smartd start";
"restartcommand[smartd]" string => "/etc/init.d/smartd restart";
"reloadcommand[smartd]" string => "/etc/init.d/smartd reload";
"stopcommand[smartd]" string => "/etc/init.d/smartd stop";
"pattern[smartd]" string => ".*smartd.*";
"startcommand[svnserve]" string => "/etc/init.d/svnserve start";
"restartcommand[svnserve]" string => "/etc/init.d/svnserve restart";
"reloadcommand[svnserve]" string => "/etc/init.d/svnserve reload";
"stopcommand[svnserve]" string => "/etc/init.d/svnserve stop";
"pattern[svnserve]" string => ".*svnserve.*";
"startcommand[syslog]" string => "/etc/init.d/syslog start";
"restartcommand[syslog]" string => "/etc/init.d/syslog restart";
"reloadcommand[syslog]" string => "/etc/init.d/syslog reload";
"stopcommand[syslog]" string => "/etc/init.d/syslog stop";
"pattern[syslog]" string => ".*syslogd.*";
"startcommand[tcsd]" string => "/etc/init.d/tcsd start";
"restartcommand[tcsd]" string => "/etc/init.d/tcsd restart";
"reloadcommand[tcsd]" string => "/etc/init.d/tcsd reload";
"stopcommand[tcsd]" string => "/etc/init.d/tcsd stop";
"pattern[tcsd]" string => ".*tcsd.*";
"startcommand[www]" string => "/etc/init.d/httpd start";
"restartcommand[www]" string => "/etc/init.d/httpd restart";
"reloadcommand[www]" string => "/etc/init.d/httpd reload";
"stopcommand[www]" string => "/etc/init.d/httpd stop";
"pattern[www]" string => ".*httpd.*";
"startcommand[xfs]" string => "/etc/init.d/xfs start";
"restartcommand[xfs]" string => "/etc/init.d/xfs restart";
"reloadcommand[xfs]" string => "/etc/init.d/xfs reload";
"stopcommand[xfs]" string => "/etc/init.d/xfs stop";
"pattern[xfs]" string => ".*xfs.*";
"startcommand[ypbind]" string => "/etc/init.d/ypbind start";
"restartcommand[ypbind]" string => "/etc/init.d/ypbind restart";
"reloadcommand[ypbind]" string => "/etc/init.d/ypbind reload";
"stopcommand[ypbind]" string => "/etc/init.d/ypbind stop";
"pattern[ypbind]" string => ".*ypbind.*";
"startcommand[yum-updatesd]" string => "/etc/init.d/yum-updatesd start";
"restartcommand[yum-updatesd]" string => "/etc/init.d/yum-updatesd restart";
"reloadcommand[yum-updatesd]" string => "/etc/init.d/yum-updatesd reload";
"stopcommand[yum-updatesd]" string => "/etc/init.d/yum-updatesd stop";
"pattern[yum-updatesd]" string => ".*yum-updatesd.*";
"startcommand[ssh]" string => "/etc/init.d/sshd start";
"restartcommand[ssh]" string => "/etc/init.d/sshd restart";
"reloadcommand[ssh]" string => "/etc/init.d/sshd reload";
"stopcommand[ssh]" string => "/etc/init.d/sshd stop";
"pattern[ssh]" string => ".*sshd.*";
debian|ubuntu::
"startcommand[atd]" string => "/etc/init.d/atd start";
"restartcommand[atd]" string => "/etc/init.d/atd restart";
"reloadcommand[atd]" string => "/etc/init.d/atd reload";
"stopcommand[atd]" string => "/etc/init.d/atd stop";
"pattern[atd]" string => "atd.*";
"startcommand[bluetoothd]" string => "/etc/init.d/bluetoothd start";
"restartcommand[bluetoothd]" string => "/etc/init.d/bluetoothd restart";
"reloadcommand[bluetoothd]" string => "/etc/init.d/bluetoothd reload";
"stopcommand[bluetoothd]" string => "/etc/init.d/bluetoothd stop";
"pattern[bluetoothd]" string => ".*bluetoothd.*";
"startcommand[bootlogd]" string => "/etc/init.d/bootlogd start";
"restartcommand[bootlogd]" string => "/etc/init.d/bootlogd restart";
"reloadcommand[bootlogd]" string => "/etc/init.d/bootlogd reload";
"stopcommand[bootlogd]" string => "/etc/init.d/bootlogd stop";
"pattern[bootlogd]" string => ".*bootlogd.*";
"startcommand[crond]" string => "/etc/init.d/cron start";
"restartcommand[crond]" string => "/etc/init.d/cron restart";
"reloadcommand[crond]" string => "/etc/init.d/cron reload";
"stopcommand[crond]" string => "/etc/init.d/cron stop";
"pattern[crond]" string => ".*cron.*";
"startcommand[kerneloops]" string => "/etc/init.d/kerneloops start";
"restartcommand[kerneloops]" string => "/etc/init.d/kerneloops restart";
"reloadcommand[kerneloops]" string => "/etc/init.d/kerneloops reload";
"stopcommand[kerneloops]" string => "/etc/init.d/kerneloops stop";
"pattern[kerneloops]" string => ".*kerneloops.*";
"startcommand[mysql]" string => "/etc/init.d/mysql start";
"restartcommand[mysql]" string => "/etc/init.d/mysql restart";
"reloadcommand[mysql]" string => "/etc/init.d/mysql reload";
"stopcommand[mysql]" string => "/etc/init.d/mysql stop";
"pattern[mysql]" string => ".*mysqld.*";
"startcommand[NetworkManager]" string => "/etc/init.d/network-manager start";
"restartcommand[NetworkManager]" string => "/etc/init.d/network-manager restart";
"reloadcommand[NetworkManager]" string => "/etc/init.d/network-manager reload";
"stopcommand[NetworkManager]" string => "/etc/init.d/network-manager stop";
"pattern[NetworkManager]" string => ".*NetworkManager.*";
"startcommand[ondemand]" string => "/etc/init.d/ondemand start";
"restartcommand[ondemand]" string => "/etc/init.d/ondemand restart";
"reloadcommand[ondemand]" string => "/etc/init.d/ondemand reload";
"stopcommand[ondemand]" string => "/etc/init.d/ondemand stop";
"pattern[ondemand]" string => ".*ondemand.*";
"startcommand[plymouth]" string => "/etc/init.d/plymouthd start";
"restartcommand[plymouth]" string => "/etc/init.d/plymouthd restart";
"reloadcommand[plymouth]" string => "/etc/init.d/plymouthd reload";
"stopcommand[plymouth]" string => "/etc/init.d/plymouthd stop";
"pattern[plymouth]" string => ".*plymouthd.*";
"startcommand[postgresql84]" string => "/etc/init.d/postgresql-8.4 start";
"restartcommand[postgresql84]" string => "/etc/init.d/postgresql-8.4 restart";
"reloadcommand[postgresql84]" string => "/etc/init.d/postgresql-8.4 reload";
"stopcommand[postgresql84]" string => "/etc/init.d/postgresql-8.4 stop";
"pattern[postgresql84]" string => ".*postgresql.*";
"startcommand[postgresql91]" string => "/etc/init.d/postgresql-9.1 start";
"restartcommand[postgresql91]" string => "/etc/init.d/postgresql-9.1 restart";
"reloadcommand[postgresql91]" string => "/etc/init.d/postgresql-9.1 reload";
"stopcommand[postgresql91]" string => "/etc/init.d/postgresql-9.1 stop";
"pattern[postgresql91]" string => ".*postgresql.*";
"startcommand[saned]" string => "/etc/init.d/saned start";
"restartcommand[saned]" string => "/etc/init.d/saned restart";
"reloadcommand[saned]" string => "/etc/init.d/saned reload";
"stopcommand[saned]" string => "/etc/init.d/saned stop";
"pattern[saned]" string => ".*saned.*";
"startcommand[udev]" string => "/etc/init.d/udev start";
"restartcommand[udev]" string => "/etc/init.d/udev restart";
"reloadcommand[udev]" string => "/etc/init.d/udev reload";
"stopcommand[udev]" string => "/etc/init.d/udev stop";
"pattern[udev]" string => ".*udev.*";
"startcommand[udevmonitor]" string => "/etc/init.d/udevmonitor start";
"restartcommand[udevmonitor]" string => "/etc/init.d/udevmonitor restart";
"reloadcommand[udevmonitor]" string => "/etc/init.d/udevmonitor reload";
"stopcommand[udevmonitor]" string => "/etc/init.d/udevmonitor stop";
"pattern[udevmonitor]" string => ".*udevadm.*monitor.*";
"startcommand[www]" string => "/etc/init.d/apache2 start";
"restartcommand[www]" string => "/etc/init.d/apache2 restart";
"reloadcommand[www]" string => "/etc/init.d/apache2 reload";
"stopcommand[www]" string => "/etc/init.d/apache2 stop";
"pattern[www]" string => ".*apache2.*";
"startcommand[ssh]" string => "/etc/init.d/ssh start";
"restartcommand[ssh]" string => "/etc/init.d/ssh restart";
"reloadcommand[ssh]" string => "/etc/init.d/ssh reload";
"stopcommand[ssh]" string => "/etc/init.d/ssh stop";
"pattern[ssh]" string => ".*sshd.*";
# METHODS that implement these ............................................
classes:
"start" expression => strcmp("start","$(state)"),
comment => "Check if to start a service";
"restart" expression => strcmp("restart","$(state)"),
comment => "Check if to restart a service";
"reload" expression => strcmp("reload","$(state)"),
comment => "Check if to reload a service";
"stop" expression => strcmp("stop","$(state)"),
comment => "Check if to stop a service";
# Do we want to include the packages here too?
processes:
start::
"$(pattern[$(service)])" -> { "@(stakeholders[$(service)])" }
comment => "Verify that the service appears in the process table",
restart_class => "start_$(service)";
stop::
"$(pattern[$(service)])" -> { "@(stakeholders[$(service)])" }
comment => "Verify that the service does not appear in the process",
process_stop => "$(stopcommand[$(service)])",
signals => { "term", "kill"};
commands:
"$(startcommand[$(service)])" -> { "@(stakeholders[$(service)])" }
comment => "Execute command to start the $(service) service",
ifvarclass => canonify("start_$(service)");
restart::
"$(restartcommand[$(service)])" -> { "@(stakeholders[$(service)])" }
comment => "Execute command to restart the $(service) service";
reload::
"$(reloadcommand[$(service)])" -> { "@(stakeholders[$(service)])" }
comment => "Execute command to reload the $(service) service";
}
##-------------------------------------------------------
## database promises
##-------------------------------------------------------
body database_server local_mysql(username, password)
{
db_server_owner => "$(username)";
db_server_password => "$(password)";
db_server_host => "localhost";
db_server_type => "mysql";
db_server_connection_db => "mysql";
}
##
body database_server local_postgresql(username, password)
{
db_server_owner => "$(username)";
db_server_password => "$(password)";
db_server_host => "localhost";
db_server_type => "postgres";
db_server_connection_db => "postgres";
}
##-------------------------------------------------------
## guest_environment promises
##-------------------------------------------------------
body environment_resources kvm(name, arch, cpu_count, mem_kb, disk_file)
{
env_spec =>
"<domain type='kvm'>
<name>$(name)</name>
<memory>$(mem_kb)</memory>
<currentMemory>$(mem_kb)</currentMemory>
<vcpu>$(cpu_count)</vcpu>
<os>
<type arch='$(arch)'>hvm</type>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<devices>
<emulator>/usr/bin/kvm</emulator>
<disk type='file' device='disk'>
<source file='$(disk_file)'/>
<target dev='vda' bus='virtio'/>
</disk>
<interface type='network'>
<source network='default'/>
</interface>
<input type='mouse' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes'/>
</devices>
</domain>";
}
####################################################
## monitor bodyparts
####################################################
body match_value scan_log(line)
{
select_line_matching => "$(line)";
track_growing_file => "true";
}
##
body match_value scan_changing_file(line)
{
select_line_matching => "$(line)";
track_growing_file => "false";
}
##
body match_value single_value(regex)
{
select_line_matching => "$(regex)";
extraction_regex => "($(regex))";
}
##
body match_value line_match_value(line_match, extract_regex)
{
select_line_matching => "$(line_match)";
extraction_regex => "$(extract_regex)";
}
##
body action sample_rate(x)
{
ifelapsed => "$(x)";
expireafter => "10";
}
bundle common paths
# In addition to defining common paths, this bundle also defines context
# classes for paths that are defined (_stdlib_has_path_xxx) and paths that
# exist (_stdlib_path_exists_xxx)
{
vars:
#
# Common full pathname of commands for OS
#
any::
"path[getfacl]" string => "/usr/bin/getfacl";
aix::
"path[awk]" string => "/usr/bin/awk";
"path[bc]" string => "/usr/bin/bc";
"path[cat]" string => "/bin/cat";
"path[cksum]" string => "/usr/bin/cksum";
"path[crontabs]" string => "/var/spool/cron/crontabs";
"path[cut]" string => "/usr/bin/cut";
"path[dc]" string => "/usr/bin/dc";
"path[df]" string => "/usr/bin/df";
"path[diff]" string => "/usr/bin/diff";
"path[dig]" string => "/usr/bin/dig";
"path[echo]" string => "/usr/bin/echo";
"path[egrep]" string => "/usr/bin/egrep";
"path[find]" string => "/usr/bin/find";
"path[grep]" string => "/usr/bin/grep";
"path[ls]" string => "/usr/bin/ls";
"path[netstat]" string => "/usr/bin/netstat";
"path[ping]" string => "/usr/bin/ping";
"path[perl]" string => "/usr/bin/perl";
"path[printf]" string => "/usr/bin/printf";
"path[sed]" string => "/usr/bin/sed";
"path[sort]" string => "/usr/bin/sort";
"path[tr]" string => "/usr/bin/tr";
freebsd|netbsd::
"path[awk]" string => "/usr/bin/awk";
"path[bc]" string => "/usr/bin/bc";
"path[cat]" string => "/bin/cat";
"path[cksum]" string => "/usr/bin/cksum";
"path[crontabs]" string => "/var/cron/tabs";
"path[cut]" string => "/usr/bin/cut";
"path[dc]" string => "/usr/bin/dc";
"path[df]" string => "/bin/df";
"path[diff]" string => "/usr/bin/diff";
"path[dig]" string => "/usr/bin/dig";
"path[echo]" string => "/bin/echo";
"path[egrep]" string => "/usr/bin/egrep";
"path[find]" string => "/usr/bin/find";
"path[grep]" string => "/usr/bin/grep";
"path[ls]" string => "/bin/ls";
"path[netstat]" string => "/usr/bin/netstat";
"path[ping]" string => "/usr/bin/ping";
"path[perl]" string => "/usr/bin/perl";
"path[printf]" string => "/usr/bin/printf";
"path[sed]" string => "/usr/bin/sed";
"path[sort]" string => "/usr/bin/sort";
"path[tr]" string => "/usr/bin/tr";
openbsd::
"path[awk]" string => "/usr/bin/awk";
"path[bc]" string => "/usr/bin/bc";
"path[cat]" string => "/bin/cat";
"path[cksum]" string => "/bin/cksum";
"path[crontabs]" string => "/var/cron/tabs";
"path[cut]" string => "/usr/bin/cut";
"path[dc]" string => "/usr/bin/dc";
"path[df]" string => "/bin/df";
"path[diff]" string => "/usr/bin/diff";
"path[dig]" string => "/usr/sbin/dig";
"path[echo]" string => "/bin/echo";
"path[egrep]" string => "/usr/bin/egrep";
"path[find]" string => "/usr/bin/find";
"path[grep]" string => "/usr/bin/grep";
"path[ls]" string => "/bin/ls";
"path[netstat]" string => "/usr/bin/netstat";
"path[ping]" string => "/usr/bin/ping";
"path[perl]" string => "/usr/bin/perl";
"path[printf]" string => "/usr/bin/printf";
"path[sed]" string => "/usr/bin/sed";
"path[sort]" string => "/usr/bin/sort";
"path[tr]" string => "/usr/bin/tr";
solaris::
"path[awk]" string => "/usr/bin/awk";
"path[bc]" string => "/usr/bin/bc";
"path[cat]" string => "/usr/bin/cat";
"path[cksum]" string => "/usr/bin/cksum";
"path[crontabs]" string => "/var/spool/cron/crontabs";
"path[cut]" string => "/usr/bin/cut";
"path[dc]" string => "/usr/bin/dc";
"path[df]" string => "/usr/bin/df";
"path[diff]" string => "/usr/bin/diff";
"path[dig]" string => "/usr/sbin/dig";
"path[echo]" string => "/usr/bin/echo";
"path[egrep]" string => "/usr/bin/egrep";
"path[find]" string => "/usr/bin/find";
"path[grep]" string => "/usr/bin/grep";
"path[ls]" string => "/usr/bin/ls";
"path[netstat]" string => "/usr/bin/netstat";
"path[ping]" string => "/usr/bin/ping";
"path[perl]" string => "/usr/bin/perl";
"path[printf]" string => "/usr/bin/printf";
"path[sed]" string => "/usr/bin/sed";
"path[sort]" string => "/usr/bin/sort";
"path[tr]" string => "/usr/bin/tr";
#
"path[svcs]" string => "/usr/bin/svcs";
"path[svcadm]" string => "/usr/sbin/svcadm";
redhat::
"path[awk]" string => "/bin/awk";
"path[bc]" string => "/usr/bin/bc";
"path[cat]" string => "/bin/cat";
"path[cksum]" string => "/usr/bin/cksum";
"path[createrepo]" string => "/usr/bin/createrepo";
"path[crontab]" string => "/usr/bin/crontab";
"path[crontabs]" string => "/var/spool/cron";
"path[cut]" string => "/bin/cut";
"path[dc]" string => "/usr/bin/dc";
"path[df]" string => "/bin/df";
"path[diff]" string => "/usr/bin/diff";
"path[dig]" string => "/usr/bin/dig";
"path[domainname]" string => "/bin/domainname";
"path[echo]" string => "/bin/echo";
"path[egrep]" string => "/bin/egrep";
"path[find]" string => "/usr/bin/find";
"path[grep]" string => "/bin/grep";
"path[hostname]" string => "/bin/hostname";
"path[init]" string => "/sbin/init";
"path[iptables]" string => "/sbin/iptables";
"path[iptables_save]" string => "/sbin/iptables-save";
"path[ls]" string => "/bin/ls";
"path[netstat]" string => "/bin/netstat";
"path[ping]" string => "/usr/bin/ping";
"path[perl]" string => "/usr/bin/perl";
"path[printf]" string => "/usr/bin/printf";
"path[sed]" string => "/bin/sed";
"path[sort]" string => "/bin/sort";
"path[sysctl]" string => "/sbin/sysctl";
"path[test]" string => "/usr/bin/test";
"path[tr]" string => "/usr/bin/tr";
#
"path[chkconfig]" string => "/sbin/chkconfig";
"path[groupadd]" string => "/usr/sbin/groupadd";
"path[groupdel]" string => "/usr/sbin/groupdel";
"path[ifconfig]" string => "/sbin/ifconfig";
"path[ip]" string => "/sbin/ip";
"path[rpm]" string => "/bin/rpm";
"path[service]" string => "/sbin/service";
"path[svc]" string => "/sbin/service";
"path[useradd]" string => "/usr/sbin/useradd";
"path[userdel]" string => "/usr/sbin/userdel";
"path[yum]" string => "/usr/bin/yum";
debian::
"path[awk]" string => "/usr/bin/awk";
"path[bc]" string => "/usr/bin/bc";
"path[cat]" string => "/bin/cat";
"path[chkconfig]" string => "/sbin/chkconfig";
"path[cksum]" string => "/usr/bin/cksum";
"path[createrepo]" string => "/usr/bin/createrepo";
"path[crontab]" string => "/usr/bin/crontab";
"path[crontabs]" string => "/var/spool/cron/crontabs";
"path[cut]" string => "/usr/bin/cut";
"path[dc]" string => "/usr/bin/dc";
"path[df]" string => "/bin/df";
"path[diff]" string => "/usr/bin/diff";
"path[dig]" string => "/usr/bin/dig";
"path[dmidecode]" string => "/usr/sbin/dmidecode";
"path[domainname]" string => "/bin/domainname";
"path[echo]" string => "/bin/echo";
"path[egrep]" string => "/bin/egrep";
"path[find]" string => "/usr/bin/find";
"path[grep]" string => "/bin/grep";
"path[hostname]" string => "/bin/hostname";
"path[ls]" string => "/bin/ls";
"path[init]" string => "/sbin/init";
"path[iptables]" string => "/sbin/iptables";
"path[iptables_save]" string => "/sbin/iptables-save";
"path[netstat]" string => "/bin/netstat";
"path[ping]" string => "/bin/ping";
"path[perl]" string => "/usr/bin/perl";
"path[printf]" string => "/usr/bin/printf";
"path[sed]" string => "/bin/sed";
"path[sort]" string => "/usr/bin/sort";
"path[sysctl]" string => "/sbin/sysctl";
"path[test]" string => "/usr/bin/test";
"path[tr]" string => "/usr/bin/tr";
#
"path[apt_cache]" string => "/usr/bin/apt-cache";
"path[apt_config]" string => "/usr/bin/apt-config";
"path[apt_get]" string => "/usr/bin/apt-get";
"path[apt_key]" string => "/usr/bin/apt-key";
"path[aptitude]" string => "/usr/bin/aptitude";
"path[dpkg]" string => "/usr/bin/dpkg";
"path[groupadd]" string => "/usr/sbin/groupadd";
"path[ifconfig]" string => "/sbin/ifconfig";
"path[ip]" string => "/sbin/ip";
"path[service]" string => "/usr/sbin/service";
"path[svc]" string => "/usr/sbin/service";
"path[update_alternatives]" string => "/usr/bin/update-alternatives";
"path[update_rc_d]" string => "/usr/sbin/update-rc.d";
"path[useradd]" string => "/usr/sbin/useradd";
any::
"all_paths" slist => getindices("path");
"$(all_paths)" string => "$(path[$(all_paths)])";
classes:
"_stdlib_has_path_$(all_paths)"
expression => isvariable("$(all_paths)"),
comment => "It's useful to know if a given path is defined";
"_stdlib_path_exists_$(all_paths)"
expression => fileexists("$(path[$(all_paths)])"),
comment => "It's useful to know if $(all_paths) exists on the filesystem as defined";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#
# Define what an agent has to do when it updates
# its promises
#
#simple copy method
body copy_from remote(server, path)
{
servers => {
"${server}"
};
encrypt => "true";
trustkey => "true";
source => "${path}";
compare => "digest";
preserve => "false"; #preserver permissions
verify => "true";
purge => "true";
community_edition::
portnumber => "5309";
}
#simple copy method, unencrypted
body copy_from remote_unsecured(server, path)
{
servers => {
"${server}"
};
encrypt => "false";
trustkey => "true";
source => "${path}";
compare => "mtime";
preserve => "true"; #preserver permissions
verify => "true";
purge => "true";
community_edition::
portnumber => "5309";
}
body copy_from copy_digest_without_perms(from)
{
source => "${from}";
copy_backup => "false";
preserve => "false";
compare => "digest";
purge => "true";
community_edition::
portnumber => "5309";
}
body copy_from remote_unsecured_without_perms(server, path)
{
servers => {
"${server}"
};
encrypt => "false";
trustkey => "true";
source => "${path}";
compare => "digest";
preserve => "false";
verify => "true";
purge => "true";
community_edition::
portnumber => "5309";
}
bundle common server_info
{
vars:
any::
"policy_files" string => "/var/rudder/share/${g.uuid}"; #directory where to look for promises in the server for that client
policy_server::
"cfserved" string => "%%POLICY_SERVER_HOSTNAME%%";
!policy_server::
"policy_server_file"
string => translatepath("${sys.workdir}/policy_server.dat"),
comment => "Path to file containing address to policy server";
"cfserved" string => readfile("${policy_server_file}", 2048);
}
# The update is now split in two parts
# - the action part, only launched during failsafe
# it copies files, restarts deamons, defines persistent classes
# - the report part, not done during failsafe but during regular run
# note that if in verbose_mode, then the reporting will be done
# as well during failsafe
#
# Since the defined class are persistent, the classes are still
# available during the "normal" agent execution, for reporting
bundle agent update
{
methods:
failsafe::
"update" usebundle => update_action;
(!failsafe|verbose_mode)::
"report" usebundle => update_reports;
reports:
# We want to have always reports if something goes bad
rudder_promises_generated_error|no_update::
"*********************************************************************************
* rudder-agent could not get an updated configuration from the policy server. *
* This can be caused by a network issue, an unavailable server, or if this *
* node was deleted from the Rudder root server. *
* Any existing configuration policy will continue to be applied without change. *
*********************************************************************************"
action => immediate;
}
bundle agent update_action
{
vars:
"client_inputs" string => "${sys.workdir}/inputs"; #where to put the files on the client when downloaded
"file_to_check_update" string => "rudder_promises_generated";
nova_edition::
"server_inputs" string => "${server_info.policy_files}/rules/cfengine-nova"; #actual directory with promises
community_edition::
"server_inputs" string => "${server_info.policy_files}/rules/cfengine-community"; #actual directory with promises
files:
any::
"${g.rudder_ncf}/."
create => "true",
comment => "Make sure the ncf directory exists";
root_server::
"${g.rudder_ncf}/common"
copy_from => copy_digest_without_perms("${g.rudder_ncf_origin_common}"),
depth_search => recurse_ignore("inf", @{g.excludedreps}),
perms => u_mog("644", "root", "root"),
action => immediate,
classes => success("rudder_ncf_common_updated", "rudder_ncf_common_update_error", "rudder_ncf_common_updated_ok"),
comment => "Update the common Rudder ncf instance";
"${g.rudder_ncf}/local"
copy_from => copy_digest_without_perms("${g.rudder_ncf_origin_local}"),
depth_search => recurse_ignore("inf", @{g.excludedreps}),
perms => u_mog("644", "root", "root"),
action => immediate,
classes => success("rudder_ncf_local_updated", "rudder_ncf_local_update_error", "rudder_ncf_local_updated_ok"),
comment => "Update the local Rudder ncf instance";
!root_server::
"${g.rudder_ncf}/common"
copy_from => remote_unsecured_without_perms("${server_info.cfserved}", "${g.rudder_ncf_origin_common}"),
depth_search => recurse_ignore("inf", @{g.excludedreps}),
perms => u_mog("644", "root", "root"),
action => immediate,
classes => success("rudder_ncf_common_updated", "rudder_ncf_common_update_error", "rudder_ncf_common_updated_ok"),
comment => "Update the common Rudder ncf instance";
"${g.rudder_ncf}/local"
copy_from => remote_unsecured_without_perms("${server_info.cfserved}", "${g.rudder_ncf_origin_local}"),
depth_search => recurse_ignore("inf", @{g.excludedreps}),
perms => u_mog("644", "root", "root"),
action => immediate,
classes => success("rudder_ncf_local_updated", "rudder_ncf_local_update_error", "rudder_ncf_local_updated_ok"),
comment => "Update the local Rudder ncf instance";
"${client_inputs}/${file_to_check_update}"
copy_from => remote("${server_info.cfserved}","${server_inputs}/${file_to_check_update}"),
action => immediate,
classes => success("rudder_promises_generated_repaired", "rudder_promises_generated_error", "rudder_promises_generated_ok");
# The defined class are persistent, so if they are already set, promises has already been updated
# a short while ago
rudder_promises_generated_repaired.!root_server::
"${client_inputs}"
copy_from => remote("${server_info.cfserved}","${server_inputs}"),
depth_search => recurse("inf"),
action => immediate,
classes => success("config", "no_update", "config_ok");
root_server|(rudder_promises_generated_ok|(rudder_promises_generated_repaired.(config|config_ok)).!no_update.!rudder_promises_generated_error)::
# Every time we check update inputs successfully (already up to date or
# updated), touch a file to let other promises know we are doing ok
"${sys.workdir}/last_successful_inputs_update"
touch => "true";
# Copy the tools only if the file rudder_tools_updated is not up to date
any::
"${g.rudder_tools_updated}"
copy_from => remote_unsecured("${server_info.cfserved}", "${g.rudder_tools_updated_origin}"),
action => immediate,
classes => success("rudder_tools_updated_repaired", "rudder_tools_updated_error", "rudder_tools_updated_kept"),
comment => "Check if we need to update the tools";
# We copy only if we have the class rudder_tools_updated_repaired
rudder_tools_updated_repaired::
"${g.rudder_tools}"
copy_from => remote_unsecured("${server_info.cfserved}", "${g.rudder_tools_origin}"),
depth_search => recurse_ignore("inf", @{g.excludedreps}),
action => immediate,
classes => success("rudder_tools_updated", "rudder_tools_update_error", "rudder_tools_updated_ok");
processes:
config.!windows::
"cf-serverd" restart_class => "start_server";
config.!windows::
"cf-execd" restart_class => "start_exec";
commands:
start_exec.!windows::
"${sys.cf_execd}"
action => u_ifwin_bg,
classes => outcome("executor");
start_exec.cygwin::
"${sys.cf_execd}"
action => u_ifwin_bg,
classes => outcome("executor");
start_server::
"${sys.cf_serverd}"
action => u_ifwin_bg,
classes => outcome("server");
#########################################################
reports:
server_ok::
"@@Common@@log_repaired@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Started the server (cf-serverd)";
executor_ok::
"@@Common@@log_repaired@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Started the scheduler (cf-execd)";
}
# This bundle is responsible for the reporting of what happened in the update
# It can work because the classes defined during the update are persistent, so
# the classes are available for the next 4 minutes
bundle agent update_reports
{
reports:
server_ok::
"@@Common@@log_repaired@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Started the server (cf-serverd)";
executor_ok::
"@@Common@@log_repaired@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Started the scheduler (cf-execd)";
no_update::
"@@Common@@result_error@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Cannot update node's policy (CFEngine promises)";
rudder_tools_update_error::
"@@Common@@result_error@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Cannot update Rudder tools";
rudder_ncf_common_update_error::
"@@Common@@result_error@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Cannot update common Rudder ncf instance";
rudder_ncf_local_update_error::
"@@Common@@result_error@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Cannot update local Rudder ncf instance";
rudder_promises_generated_error::
"@@Common@@result_error@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Cannot update node's policy";
(rudder_promises_generated_ok|(rudder_tools_updated_ok.rudder_ncf_common_updated_ok.rudder_ncf_local_updated_ok.config_ok)).!(rudder_promises_generated_repaired|rudder_promises_generated_error|rudder_tools_updated|rudder_tools_update_error|rudder_ncf_common_updated|rudder_ncf_common_update_error|rudder_ncf_local_updated|rudder_ncf_local_update_error|config|no_update)::
"@@Common@@result_success@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Rudder policy, tools and ncf instance are already up to date. No action required.";
rudder_tools_updated::
"@@Common@@log_repaired@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Rudder tools updated";
rudder_ncf_common_updated::
"@@Common@@log_repaired@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Rudder ncf common instance updated";
rudder_ncf_local_updated::
"@@Common@@log_repaired@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Rudder ncf local instance updated";
config::
"@@Common@@log_repaired@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Node's policy (CFEngine promises) updated";
rudder_promises_generated_repaired|config|rudder_tools_updated|rudder_ncf_common_updated|rudder_ncf_local_updated|server_ok|executor_ok::
"@@Common@@result_repaired@@hasPolicyServer-root@@common-root@@00@@Update@@None@@${g.execRun}##${g.uuid}@#Policy or dependencies were updated or CFEngine service restarted";
}
############################################
body classes outcome(x)
{
promise_repaired => {"${x}_ok"};
}
############################################
body action u_background
{
background => "true";
}
############################################
body classes success(if, else, kept)
{
promise_kept => { "${kept}" };
promise_repaired => {"${if}"};
repair_failed => { "${else}" };
repair_denied => { "${else}" };
repair_timeout => { "${else}" };
# persist for 4 minutes so that it wont overlap with the next
# execution in 5 minutes
persist_time => "4";
}
############################################
body action u_ifwin_bg
{
windows::
background => "true";
}
body service_method u_bootstart
{
service_autostart_policy => "boot_time";
}
body perms u_mog(mode,user,group)
{
owners => { "${user}" };
groups => { "${group}" };
mode => "${mode}";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent internal_security
{
vars:
!windows::
"mode" string => "600";
"user" string => "root";
"group" string => "0";
#windows::
# "mode" string => "755";
# "user" string => "Administrator";
# "group" string => "Administrators";
files:
!windows::
"${g.rudder_var}/cfengine-community/inputs"
depth_search => recurse("inf"),
perms => mog("${mode}", "${user}", "${group}"),
classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed");
"${g.rudder_var}/cfengine-community/inputs"
perms => mog("${mode}", "${user}", "${group}"),
classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed");
"${g.rudder_var}/cfengine-community/ppkeys"
depth_search => recurse("inf"),
perms => mog("${mode}", "${user}", "${group}"),
classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed");
"${g.rudder_var}/cfengine-community/ppkeys"
perms => mog("${mode}", "${user}", "${group}"),
classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed");
reports:
security_sanitization_ok.!security_sanitization_repaired::
"@@Common@@result_success@@hasPolicyServer-root@@common-root@@00@@Security parameters@@None@@${g.execRun}##${g.uuid}@#The internal environment security is acceptable";
security_sanitization_repaired::
"@@Common@@result_repaired@@hasPolicyServer-root@@common-root@@00@@Security parameters@@None@@${g.execRun}##${g.uuid}@#Some internal security parameters were adjusted";
security_sanitization_failed::
"@@Common@@result_error@@hasPolicyServer-root@@common-root@@00@@Security parameters@@None@@${g.execRun}##${g.uuid}@#The internal environment security is NOT acceptable!";
windows::
"@@Common@@result_success@@hasPolicyServer-root@@common-root@@00@@Security parameters@@None@@${g.execRun}##${g.uuid}@#No internal security parameters defined for Windows OSes yet";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
bundle agent process_matching
{
vars:
# This deliberately excludes cf-execd which is handled separately below
"cf_components" slist => { "cf-key",
# "cf-monitord", Disabled
"cf-promises",
"cf-runagent", "cf-serverd" };
windows::
"stop_signal" string => "kill";
!windows::
"stop_signal" string => "term";
classes:
"restart_cf" expression => "Hr05.Min00_05";
files:
!windows.!android::
# This is to cleanup /etc/crontab from pre-2.5 usage
# and initial promises before 2.7
"${g.crontab}"
create => "true",
edit_defaults => noempty_backup,
edit_line => cron_cleanup;
# Temporary cron file added by rudder-agent postinst to prevent from UUID removal.
# When this promise will be generated, this cron will be useless then removed.
# (see http://www.rudder-project.org/redmine/issues/3925 and http://www.rudder-project.org/redmine/issues/3930).
"/etc/cron.d/rudder-agent-uuid" delete => tidy;
community_edition.!aix::
"/etc/cron.d/rudder-agent"
create => "true",
perms => mog("644", "root", "root"),
edit_defaults => empty_backup,
edit_line => expand_template("${sys.workdir}/inputs/common/cron/rudder_agent_community_cron");
aix::
"/var/spool/cron/crontabs/root"
create => "true",
perms => mog("600", "root", "cron"),
edit_line => insert_lines("0,5,10,15,20,25,30,35,40,45,50,55 * * * * if [ -x /opt/rudder/bin/check-rudder-agent ]; then /opt/rudder/bin/check-rudder-agent; fi"),
classes => rudder_common_classes("rudder_aix_crontab_insertion"),
comment => "Insert an AIX-compatible user crontab to run /opt/rudder/bin/check-rudder-agent";
processes:
windows::
# Always stop cf-monitord
"${g.escaped_workdir}\/bin\/cf-monitord" signals => { "${stop_signal}" };
!windows::
# Always stop cf-monitord
"${sys.workdir}/bin/cf-monitord" signals => { "${stop_signal}" };
restart_cf.!policy_server::
"${cf_components}" signals => { "${stop_signal}" };
# Policy servers have both Nova and Community, don't blindly kill the wrong processes
restart_cf.policy_server::
"${sys.workdir}/bin/${cf_components}" signals => { "${stop_signal}" };
restart_cf.!windows::
"${sys.workdir}/bin/cf-execd" signals => { "${stop_signal}" };
# Note: cron will get restarted automatically by init (respawn directive in inittab)
aix.rudder_aix_crontab_insertion::
"^/usr/sbin/cron" signals => { "${stop_signal}" };
commands:
restart_cf.!windows::
"${sys.cf_serverd}";
"${sys.cf_execd}";
reports:
restart_cf::
"Reloaded configuration of all Cfengine components";
}
# This is to cleanup /etc/crontab from pre-2.5 usage
# and initial promises before 2.7
bundle edit_line cron_cleanup
{
# Remove old lines to replace them with new version
delete_lines:
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ \`ps -efww \| grep cf-execd \| grep \"/var/cfengine/bin/cf-execd\" \| grep -v grep \| wc -l\` -eq 0 \]; then /var/cfengine/bin/cf-execd; fi";
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ \`ps -efww \| grep cf-execd \| grep \"/var/rudder/cfengine-community/bin/cf-execd\" \| grep -v grep \| wc -l\` -eq 0 \]; then /var/rudder/cfengine-community/bin/cf-execd; fi";
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ ! -e /opt/rudder/etc/disable-agent -a \`ps -efww \| grep cf-execd \| grep \"/var/rudder/cfengine-community/bin/cf-execd\" \| grep -v grep \| wc -l\` -eq 0 \]; then /var/rudder/cfengine-community/bin/cf-execd; fi";
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ ! -e /opt/rudder/etc/disable-agent -a \`ps -efww \| grep cf-execd \| grep \"/var/cfengine/bin/cf-execd\" \| grep -v grep \| wc -l\` -eq 0 \]; then /var/cfengine/bin/cf-execd; fi";
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ ! -e /opt/rudder/etc/disable-agent -a \`ps -efww \| grep cf-execd \| grep \"/var/cfengine/bin/cf-execd\" \| grep -v grep \| wc -l\` -eq 0 \]; then /var/cfengine/bin/cf-agent -f failsafe.cf \&\& /var/cfengine/bin/cf-agent; fi";
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ ! -e /opt/rudder/etc/disable-agent -a \`ps -efww \| grep cf-execd \| grep \"/var/rudder/cfengine-community/bin/cf-execd\" \| grep -v grep \| wc -l\` -eq 0 \]; then /var/rudder/cfengine-community/bin/cf-agent -f failsafe.cf \&\& /var/rudder/cfengine-community/bin/cf-agent; fi";
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ ! -e /opt/rudder/etc/disable-agent -a \`ps -efww \| grep -E \"\(cf-execd\|cf-agent\)\" \| grep -E \"/var/cfengine/bin/\(cf-execd\|cf-agent\)\" \| grep -v grep \| wc -l\` -eq 0 ]; then /var/cfengine/bin/cf-agent -f failsafe.cf \&\& /var/cfengine/bin/cf-agent; fi";
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ ! -e /opt/rudder/etc/disable-agent -a \`ps -efww \| grep -E \"\(cf-execd\|cf-agent\)\" \| grep -E \"/var/rudder/cfengine-community/bin/\(cf-execd\|cf-agent\)\" \| grep -v grep \| wc -l\` -eq 0 ]; then /var/rudder/cfengine-community/bin/cf-agent -f failsafe.cf \&\& /var/rudder/cfengine-community/bin/cf-agent; fi";
# Remove entry with wrong escapements from /etc/crontab
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ ! -e /opt/rudder/etc/disable-agent -a \`ps -efww \| grep -E \"\(cf-execd\|cf-agent\)\" \| grep -E \"/var/rudder/cfengine-community/bin/\(cf-execd\|cf-agent\)\" \| grep -v grep \| wc -l\` -eq 0 ]; then /var/rudder/cfengine-community/bin/cf-agent -f failsafe.cf \\\&\\\& /var/rudder/cfengine-community/bin/cf-agent; fi";
}
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################
#######################################################
#
# Server specific configuration
#
#######################################################
bundle server access_rules
{
# Access rules are only defined on a policy server. Standard nodes should not share any files.
access:
policy_server::
"${def.dir_masterfiles}"
handle => "grant_access_policy",
comment => "Grant access to the policy updates",
maproot => { @{def.acl} },
admit => { @{def.acl} };
"${g.rudder_tools}"
maproot => { @{def.acl} },
admit => { @{def.acl} };
"${g.rudder_ncf_origin_common}"
maproot => { @{def.acl} },
admit => { @{def.acl} };
"${g.rudder_ncf_origin_local}"
maproot => { @{def.acl} },
admit => { @{def.acl} };
"/var/rudder/share/root/"
maproot => { host2ip("${server_info.cfserved}"), escape("${server_info.cfserved}") },
admit => { host2ip("${server_info.cfserved}"), escape("${server_info.cfserved}") };
# the policy server must have access to the cfengine folder
"${sys.workdir}"
maproot => { host2ip("${server_info.cfserved}"), escape("${server_info.cfserved}") },
admit => { host2ip("${server_info.cfserved}"), escape("${server_info.cfserved}") };
roles:
# Allow user root to set any class
".*" authorize => { "root" };
}
bundle common def
{
vars:
"policy_server_file" string => translatepath("${sys.workdir}/policy_server.dat"),
comment => "Path to file containing address to policy server";
"policy_server" string => readfile("${policy_server_file}", 2048),
comment => "IP address or hostname to locate your policy host.";
"dir_masterfiles" string => translatepath("${sys.workdir}/masterfiles");
# List here the IP masks that we grant access to on the server
policy_server::
"acl" slist => {
'%%POLICY_SERVER_ALLOWED_NETWORKS%%'
};
!policy_server::
"acl" slist => {
"${def.policy_server}"
};
}
body server control
{
trustkeysfrom => {
"127.0.0.0/8" , "::1",
@{def.acl} ,
host2ip("${server_info.cfserved}"), "${server_info.cfserved}"
}; #trustkey allows the exchange of keys
allowconnects => {
@{def.acl} ,
host2ip("${server_info.cfserved}"), "${server_info.cfserved}"
};
maxconnections => "1000";
logallconnections => "true";
cfruncommand => "${sys.workdir}/bin/cf-agent -f failsafe.cf && ${sys.workdir}/bin/cf-agent";
allowusers => { "root" };
skipverify => { "127.0.0.0/8" , "::1", @{def.acl} };
community_edition::
port => "5309";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment