From 4a86a0b47f4e94a9810e225de65bcd1e26f3af7a Mon Sep 17 00:00:00 2001 From: Alexis Mousset Date: Wed, 9 Jan 2019 18:14:38 +0100 Subject: [PATCH] Fixes #14128: Split ncf_lib like cfengine lib --- tree/20_cfe_basics/commands.cf | 23 + tree/20_cfe_basics/common.cf | 346 +++ .../{dry_run_lib.cf => dry_run.cf} | 16 +- tree/20_cfe_basics/dry_run_lib.unsupported.cf | 46 - tree/20_cfe_basics/files.cf | 703 ++++++ tree/20_cfe_basics/{flag_lib.cf => flags.cf} | 19 +- tree/20_cfe_basics/log_rudder.cf | 97 +- tree/20_cfe_basics/logger_rudder.cf | 43 - tree/20_cfe_basics/ncf_lib.cf | 1954 ----------------- tree/20_cfe_basics/old_packages.cf | 537 +++++ .../{package_lib.cf => packages.cf} | 1 - tree/20_cfe_basics/paths.cf | 37 + tree/20_cfe_basics/processes.cf | 34 + tree/20_cfe_basics/services.cf | 351 +++ tree/20_cfe_basics/storage.cf | 28 + tree/20_cfe_basics/{time_lib.cf => time.cf} | 4 - 16 files changed, 2133 insertions(+), 2106 deletions(-) create mode 100644 tree/20_cfe_basics/commands.cf create mode 100644 tree/20_cfe_basics/common.cf rename tree/20_cfe_basics/{dry_run_lib.cf => dry_run.cf} (96%) delete mode 100644 tree/20_cfe_basics/dry_run_lib.unsupported.cf create mode 100644 tree/20_cfe_basics/files.cf rename tree/20_cfe_basics/{flag_lib.cf => flags.cf} (98%) delete mode 100644 tree/20_cfe_basics/logger_rudder.cf delete mode 100644 tree/20_cfe_basics/ncf_lib.cf create mode 100644 tree/20_cfe_basics/old_packages.cf rename tree/20_cfe_basics/{package_lib.cf => packages.cf} (99%) create mode 100644 tree/20_cfe_basics/paths.cf create mode 100644 tree/20_cfe_basics/processes.cf create mode 100644 tree/20_cfe_basics/services.cf create mode 100644 tree/20_cfe_basics/storage.cf rename tree/20_cfe_basics/{time_lib.cf => time.cf} (99%) diff --git a/tree/20_cfe_basics/commands.cf b/tree/20_cfe_basics/commands.cf new file mode 100644 index 000000000..031973c28 --- /dev/null +++ b/tree/20_cfe_basics/commands.cf @@ -0,0 +1,23 @@ +##################################################################################### +# Copyright 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 . +# +##################################################################################### + +body contain outputable +{ + useshell => "true"; + no_output => "false"; +} diff --git a/tree/20_cfe_basics/common.cf b/tree/20_cfe_basics/common.cf new file mode 100644 index 000000000..12682db0c --- /dev/null +++ b/tree/20_cfe_basics/common.cf @@ -0,0 +1,346 @@ +##################################################################################### +# Copyright 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 . +# +##################################################################################### + +# Constants definitions +bundle common ncf_const +{ + vars: + "s" string => " "; +} + +# Don't do anything if class warn is defined, or remediate the promises +# if immediate is defined (default action) +# DEPRECATED: warn and immediate need to be global classes, use policy(p) instead. +body action do_if_immediate +{ + warn|dry_run|global_dry_run:: + action_policy => "warn"; +} + +# Useful for immediate call to bundles with dry-run mode on, +# as we do not want dry-run mode applied on it. +body action immediate_ignore_dry_run +{ + ifelapsed => "0"; +} + +body action WarnOnly +{ + action_policy => "warn"; +} + +# Define x prefixes/suffixed with promises outcome, based on return codes +# !DEPRECATED! +body classes classes_generic_return_codes(x, kept_return_code, repaired_return_code, failed_return_code) +{ + kept_returncodes => { "${kept_return_code}" }; + repaired_returncodes => { "${repaired_return_code}" }; + failed_returncodes => { "${failed_return_code}" }; + + 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", "${x}_error" }; + repair_denied => { "repair_denied_$(x)", "$(x)_denied", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error" }; + repair_timeout => { "repair_timeout_$(x)", "$(x)_timeout", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error" }; + promise_kept => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached" }; +} + +# Define x prefixes/suffixed with promises outcome, based on return codes +body classes classes_generic_return_single_code_two(x, y, kept_return_code, repaired_return_code, failed_return_code) +{ + kept_returncodes => { "${kept_return_code}" }; + repaired_returncodes => { "${repaired_return_code}" }; + failed_returncodes => { "${failed_return_code}" }; + + promise_repaired => { "promise_repaired_$(x)", "$(x)_repaired", "$(x)_ok", "$(x)_reached", + "promise_repaired_$(y)", "$(y)_repaired", "$(y)_ok", "$(y)_reached" }; + repair_failed => { "repair_failed_$(x)", "$(x)_failed", "$(x)_not_ok", "$(x)_error", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", + "repair_failed_$(y)", "$(y)_failed", "$(y)_not_ok", "$(y)_error", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached" }; + repair_denied => { "repair_denied_$(x)", "$(x)_denied", "$(x)_not_ok", "$(x)_error", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", + "repair_denied_$(y)", "$(y)_denied", "$(y)_not_ok", "$(y)_error", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached" }; + repair_timeout => { "repair_timeout_$(x)", "$(x)_timeout", "$(x)_not_ok", "$(x)_error", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", + "repair_timeout_$(y)", "$(y)_timeout", "$(y)_not_ok", "$(y)_error", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached" }; + promise_kept => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached", + "promise_kept_$(y)", "$(y)_kept", "$(y)_ok", "$(y)_not_repaired", "$(y)_reached" }; +} + +# Define x prefixes/suffixed with promises outcome, based on return codes +body classes classes_generic_return_code_list_two(x, y, kept_return_codes, repaired_return_codes) +{ + kept_returncodes => { @{kept_return_codes} }; + repaired_returncodes => { @{repaired_return_codes} }; + + promise_repaired => { "promise_repaired_$(x)", "$(x)_repaired", "$(x)_ok", "$(x)_reached", + "promise_repaired_$(y)", "$(y)_repaired", "$(y)_ok", "$(y)_reached" }; + repair_failed => { "repair_failed_$(x)", "$(x)_failed", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error", + "repair_failed_$(y)", "$(y)_failed", "$(y)_not_ok", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached", "${y}_error" }; + repair_denied => { "repair_denied_$(x)", "$(x)_denied", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error", + "repair_denied_$(y)", "$(y)_denied", "$(y)_not_ok", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached", "${y}_error"}; + repair_timeout => { "repair_timeout_$(x)", "$(x)_timeout", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error", + "repair_timeout_$(y)", "$(y)_timeout", "$(y)_not_ok", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached", "${y}_error" }; + promise_kept => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached", + "promise_kept_$(y)", "$(y)_kept", "$(y)_ok", "$(y)_not_repaired", "$(y)_reached" }; +} + +# Define x prefixes/suffixed with true/false outcome, based on return codes +# Note that an unknown return code is an error and doesn't return false nor true, just an error. +body classes classes_generic_return_boolean_list_two(x, y, boolean_prefix, true_return_codes, false_return_codes) +{ + kept_returncodes => { @{true_return_codes} }; + repaired_returncodes => { @{false_return_codes} }; + + promise_repaired => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached", + "promise_kept_$(y)", "$(y)_kept", "$(y)_ok", "$(y)_not_repaired", "$(y)_reached", "${boolean_prefix}_false" }; + repair_failed => { "repair_failed_$(x)", "$(x)_failed", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error", + "repair_failed_$(y)", "$(y)_failed", "$(y)_not_ok", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached", "${y}_error" }; + repair_denied => { "repair_denied_$(x)", "$(x)_denied", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error", + "repair_denied_$(y)", "$(y)_denied", "$(y)_not_ok", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached", "${y}_error" }; + repair_timeout => { "repair_timeout_$(x)", "$(x)_timeout", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error", + "repair_timeout_$(y)", "$(y)_timeout", "$(y)_not_ok", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached", "${y}_error" }; + promise_kept => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached", + "promise_kept_$(y)", "$(y)_kept", "$(y)_ok", "$(y)_not_repaired", "$(y)_reached", "${boolean_prefix}_true" }; +} + +# Define x and y prefixed/suffixed with promise outcome +body classes classes_generic_two(x,y) +{ + promise_repaired => { "promise_repaired_$(x)", "$(x)_repaired", "$(x)_ok", "$(x)_reached", + "promise_repaired_$(y)", "$(y)_repaired", "$(y)_ok", "$(y)_reached" }; + repair_failed => { "repair_failed_$(x)", "$(x)_failed", "$(x)_not_ok", "$(x)_error", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", + "repair_failed_$(y)", "$(y)_failed", "$(y)_not_ok", "$(y)_error", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached" }; + repair_denied => { "repair_denied_$(x)", "$(x)_denied", "$(x)_not_ok", "$(x)_error", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", + "repair_denied_$(y)", "$(y)_denied", "$(y)_not_ok", "$(y)_error", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached" }; + repair_timeout => { "repair_timeout_$(x)", "$(x)_timeout", "$(x)_not_ok", "$(x)_error", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", + "repair_timeout_$(y)", "$(y)_timeout", "$(y)_not_ok", "$(y)_error", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached" }; + promise_kept => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached", + "promise_kept_$(y)", "$(y)_kept", "$(y)_ok", "$(y)_not_repaired", "$(y)_reached" }; +} + +body classes common_classes_exclusive_persist_codes(prefix, persist, keptcodes, repairedcodes, errorcodes) +{ + kept_returncodes => { "@{keptcodes}" }; + repaired_returncodes => { "@{repairedcodes}" }; + failed_returncodes => { "@{errorcodes}" }; + + promise_kept => { "${prefix}_kept" , "${prefix}_ok" }; + cancel_kept => { "${prefix}_repaired", "${prefix}_failed", "${prefix}_error" }; + + promise_repaired => { "${prefix}_repaired", "${prefix}_ok" }; + cancel_repaired => { "${prefix}_kept", "${prefix}_failed", "${prefix}_error" }; + + repair_failed => { "${prefix}_failed" , "${prefix}_error" }; + repair_denied => { "${prefix}_denied" , "${prefix}_error" }; + repair_timeout => { "${prefix}_timeout" , "${prefix}_error" }; + cancel_notkept => { "${prefix}_kept", "${prefix}_ok", "${repaired}" }; + + persist_time => "${persist}"; +} + +########################################################################################### +# 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 persistent_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 +################################################ +# DEPRECATED +body classes kept_if_else(kept, yes,no) +{ + promise_kept => { "${kept}" }; + promise_repaired => { "${yes}" }; + repair_failed => { "${no}" }; + repair_denied => { "${no}" }; + repair_timeout => { "${no}" }; +} + +# DEPRECATED +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}" }; +} + +########################################################################################### +# 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}" }; +} + +# Combines classes from two specified prefixes +# The worst outcome is kept (logical AND) +bundle agent ncf_classes_combine_two(first_prefix, second_prefix, destination_prefix) +{ + classes: + "first_reached" expression => "${first_prefix}_reached"; + "second_reached" expression => "${second_prefix}_reached"; + + destination_exists.first_reached.second_reached:: + "${destination_prefix}_ok" expression => "${first_prefix}_ok.${second_prefix}_ok", + scope => "namespace"; + + "${destination_prefix}_kept" expression => "${first_prefix}_kept.${second_prefix}_kept", + scope => "namespace"; + + "promise_kept_${destination_prefix}" expression => "${destination_prefix}_kept", + scope => "namespace"; + + "${destination_prefix}_repaired" expression => "(${first_prefix}_ok.${second_prefix}_repaired)|(${first_prefix}_repaired.${second_prefix}_ok)", + scope => "namespace"; + + "promise_repaired_${destination_prefix}" expression => "${destination_prefix}_repaired", + scope => "namespace"; + + "${destination_prefix}_reached" expression => "${first_prefix}_reached|${second_prefix}_reached", + scope => "namespace"; + + "${destination_prefix}_failed" expression => "${first_prefix}_failed|${second_prefix}_failed", + scope => "namespace"; + + "repair_failed_${destination_prefix}" expression => "${destination_prefix}_failed", + scope => "namespace"; + + "${destination_prefix}_denied" expression => "${first_prefix}_denied|${second_prefix}_denied", + scope => "namespace"; + + "repair_denied_${destination_prefix}" expression => "${destination_prefix}_denied", + scope => "namespace"; + + "${destination_prefix}_timeout" expression => "${first_prefix}_timeout|${second_prefix}_timeout", + scope => "namespace"; + + "repair_timeout_${destination_prefix}" expression => "${destination_prefix}_timeout", + scope => "namespace"; + + "${destination_prefix}_error" expression => "${first_prefix}_error|${second_prefix}_error", + scope => "namespace"; + + "${destination_prefix}_not_ok" expression => "!${destination_prefix}_ok", + scope => "namespace"; + + "${destination_prefix}_not_kept" expression => "!${destination_prefix}_kept", + scope => "namespace"; + + "${destination_prefix}_not_repaired" expression => "!${destination_prefix}_repaired", + scope => "namespace"; + + classes: + # this line will not be evaluated by cfengine if destination_prefix contains a variable that does not exist + # and it will always be evaluated to true otherwise + "destination_defined" expression => strcmp("${destination_prefix}", "${destination_prefix}"); + "destination_not_empty" not => strcmp("${destination_prefix}", ""); + "destination_exists" and => { "destination_defined", "destination_not_empty" }; + + methods: + first_reached.!second_reached:: + "copy first" usebundle => _classes_copy("${first_prefix}", "${destination_prefix}"); + + !first_reached.second_reached:: + "copy second" usebundle => _classes_copy("${second_prefix}", "${destination_prefix}"); +} + +# Copies classes with source_prefix into destination_prefix +# This copies the whole class set +bundle agent ncf_classes_copy(source_prefix, destination_prefix) +{ + vars: + "prefix" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout" }; + "suffix" slist => { "repaired", "ok", "reached", "failed", "not_ok", "not_kept", "not_repaired", "denied", "timeout", "kept", "error" }; + + destination_exists:: + # Copy result classes prefixes + "${prefix}_local_destination_prefix" + string => "${prefix}_${destination_prefix}", + ifvarclass => "${prefix}_${source_prefix}", + classes => always("${prefix}_${destination_prefix}"); + + # Copy result classes suffixes + "local_destination_prefix_${suffix}" + string => "${destination_prefix}_${suffix}", + ifvarclass => "${source_prefix}_${suffix}", + classes => always("${destination_prefix}_${suffix}"); + + classes: + # this line will not be evaluated by cfengine if destination_prefix contains a variable that does not exist + # and it will always be evaluated to true otherwise + "destination_defined" expression => strcmp("${destination_prefix}", "${destination_prefix}"); + "destination_not_empty" not => strcmp("${destination_prefix}", ""); + "destination_exists" and => { "destination_defined", "destination_not_empty" }; +} diff --git a/tree/20_cfe_basics/dry_run_lib.cf b/tree/20_cfe_basics/dry_run.cf similarity index 96% rename from tree/20_cfe_basics/dry_run_lib.cf rename to tree/20_cfe_basics/dry_run.cf index b98d2f84f..c5b340422 100644 --- a/tree/20_cfe_basics/dry_run_lib.cf +++ b/tree/20_cfe_basics/dry_run.cf @@ -72,7 +72,6 @@ # WARNING: # # @parameter mode The dry-run mode, "true" to enable dry-run-mode and "false" to disable it -# @agent_requirements "capabilities": [ "bodydefault" ] || "agent_version" >= 3.9 # bundle agent set_dry_run_mode(mode) @@ -80,16 +79,17 @@ bundle agent set_dry_run_mode(mode) vars: # this is a way to remove the class without side effect pass2.unset_mode:: - "ignored" string => "", classes => if_ok_cancel("dry_run"); + "ignored" string => "", + classes => if_ok_cancel("dry_run"); classes: # double negation, so that the default is dry_run (in case of error) "unset_mode" expression => strcmp("${mode}", "false"); - "pass2" expression => "pass1"; - "pass1" expression => "any"; + "pass2" expression => "pass1"; + "pass1" expression => "any"; pass2.!unset_mode:: - "dry_run" expression => "any", scope => "namespace"; + "dry_run" expression => "any", scope => "namespace"; reports: pass2.debug.unset_mode:: @@ -105,12 +105,13 @@ bundle agent set_dry_run_mode(mode) # This bundle initializes the context for push/pop # It is called in 10_ncf_internals/initialization.cf -bundle agent dry_run_initialization { +bundle agent dry_run_initialization +{ vars: # designed to be incremented when a global unique ID is needed "dry_run_unique.value" string => "1"; # stack of dry_run modes - "dry_run_unique.stack" slist => {}; + "dry_run_unique.stack" slist => {}; } # Push current dry-run mode to the stack and set a new mode instead. @@ -271,4 +272,3 @@ body file control { namespace => "default"; } - diff --git a/tree/20_cfe_basics/dry_run_lib.unsupported.cf b/tree/20_cfe_basics/dry_run_lib.unsupported.cf deleted file mode 100644 index 6775aa186..000000000 --- a/tree/20_cfe_basics/dry_run_lib.unsupported.cf +++ /dev/null @@ -1,46 +0,0 @@ -##################################################################################### -# Copyright 2016 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 . -# -##################################################################################### - -# @parameter mode The dry-run mode, "true" to enable dry-run-mode and "false" to disable it -# @agent_requirements "capabilities": [ "!bodydefault" ] && "agent_version" < 3.9 -# -# See dry_run_lib.cf for documentation. -# -# WARNING: -# WARNING: This bundles replaces the real dry-run lib when it is not supported, and -# WARNING: aborts when trying to enable dry-run mode. -# WARNING: -# WARNING: The global_dry_run class and the _dry_run class are ignored by this bundle -# WARNING: and using them on systems that do not support it will lead to enforce -# WARNING: configuration that should only by in dry-run mode. -# WARNING: -bundle agent set_dry_run_mode(mode) -{ - classes: - # double negation, so that the default is dry_run (in case of error) - "unset_mode" expression => strcmp("${mode}", "false"); - - methods: - !unset_mode:: - "abort" usebundle => _abort("unsupported_dryrun", "Dry-run mode is not compatible with this agent. Stopping immediately to prevent any unwanted change."), - action => immediate_ignore_dry_run; - - reports: - debug.unset_mode:: - "${configuration.debug} Dry-run mode is not compatible with this agent, but only a disabling of dry-run has been requested. Ignoring."; -} diff --git a/tree/20_cfe_basics/files.cf b/tree/20_cfe_basics/files.cf new file mode 100644 index 000000000..0f1fbebe1 --- /dev/null +++ b/tree/20_cfe_basics/files.cf @@ -0,0 +1,703 @@ +##################################################################################### +# Copyright 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 . +# +##################################################################################### + + +bundle edit_line ncf_insert_block(block) +{ + insert_lines: + "${block}" + insert_type => "preserve_block", + comment => "Append a text block if it does not exist"; +} + +# Sets the RHS of configuration items with a given separator +# supports keys that contains special characters (like *, ?) +# This bundle will allow any quantity of spaces before the separator, but none +# between the separator and the value +bundle edit_line ncf_maintain_keys_values(v, sep) +{ + vars: + "index" slist => getindices("${v}"); + # Be careful if the index string contains funny chars + "cindex[${index}]" string => canonify("${index}"); + + # Keys and values may contain regexps. Escape them for replace_pattern matching. + "ve[${index}]" string => escape("${${v}[${index}]}"); + "ke[${index}]" string => escape("${index}"); + "separator" string => escape("${sep}"); + + # Matching pattern for line (basically key-and-separator) + "keypat[${index}]" string => "\s*${ke[${index}]}\s*${separator}\s*"; + + classes: + "${cindex[${index}]}_key_in_file" + comment => "Dynamic Class created if patterns matching", + expression => regline("^${keypat[${index}]}.*", "${edit.filename}"); + + insert_lines: + "${index}${sep}${${v}[${index}]}" + comment => "Insert definition of ${index}", + ifvarclass => "!${cindex[${index}]}_key_in_file"; + + 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}]}"); +} + +# Sets the RHS of configuration items with a given separator +# supports keys that contains special characters (like *, ?), with option to be strict or not +# by default, treat non strictly spacing. If option is "strict", then no space will be allowed +bundle edit_line ncf_maintain_keys_values_option(v, sep, option) +{ + vars: + "index" slist => getindices("${v}"); + # Be careful if the index string contains funny chars + "cindex[${index}]" string => canonify("${index}"); + + # Keys and values may contain regexps. Escape them for replace_pattern matching. + "ve[${index}]" string => escape("${${v}[${index}]}"); + "ke[${index}]" string => escape("${index}"); + "separator" string => escape("${sep}"); + + # Matching pattern for line (basically key-and-separator) + "keypat[${index}]" string => "\s*${ke[${index}]}\s*${separator}\s*"; + + + classes: + "strict_spacing" expression => strcmp("${option}", "strict"); + + "${cindex[${index}]}_key_in_file" + comment => "Dynamic Class created if patterns matching", + expression => regline("^${keypat[${index}]}.*", "${edit.filename}"); + + !strict_spacing:: + "${cindex[${index}]}_key_value_in_file" + comment => "Dynamic Class created if in loose mode, key\s*separator\s*value is there", + expression => regline("^${keypat[${index}]}${ve[${index}]}\s*", "${edit.filename}"); + + + insert_lines: + "${index}${sep}${${v}[${index}]}" + comment => "Insert definition of ${index}", + ifvarclass => "!${cindex[${index}]}_key_in_file"; + + replace_patterns: + # For convergence need to use negative lookahead on value: + # "key sep (?!value).*" + strict_spacing:: + "^(\s*${ke[${index}]}\s*${separator}\s*)(?!${ve[${index}]}$).*" + comment => "Strict replace definition of ${index}", + replace_with => value("${ke[${index}]}${sep}${${v}[${index}]}"); + + !strict_spacing:: + "^(\s*${ke[${index}]}\s*${separator}\s*)(?!${ve[${index}]}$).*" + comment => "Replace definition of ${index}", + replace_with => value("${match.1}${${v}[${index}]}"), + ifvarclass => "!${cindex[${index}]}_key_value_in_file"; +} + +# enforce lines in section +# WARNING: This bundle is deprecated and will be removed. +# You should use ncf_ensure_section_content_type with the "literal" insert type. +bundle edit_line ncf_ensure_section_content(section_start, section_end, content) +{ + vars: + "csection" string => canonify("$(section_start)"); + "escaped_section_start" string => escape(${section_start}); + "escaped_section_end" string => escape(${section_end}); + + classes: + # Detect if section is already there + "has_$(csection)" expression => regline("${escaped_section_start}", "$(edit.filename)"); + + delete_lines: + ".*" + select_region => ncf_section_selector("${escaped_section_start}", "${escaped_section_end}"), + ifvarclass => "has_$(csection)"; + + insert_lines: + # Insert new, empty section if it doesn't exist already. + "${section_start} +${section_end}" + insert_type => "preserve_block", + ifvarclass => "!has_$(csection)"; + + # Insert missing lines into the section + "$(content)" + select_region => ncf_section_selector("${escaped_section_start}", "${escaped_section_end}"); +} + +# Enforce content in section. +# It will create the section if it does not exist yet. +# You can choose the insert_type: +# * Use "preserve_block" to insert blocks of text +# * Use "literal" to insert independant lines +bundle edit_line ncf_ensure_section_content_type(section_start, section_end, content, insert_type) +{ + vars: + "csection" string => canonify("$(section_start)"); + "escaped_section_start" string => escape(${section_start}); + "escaped_section_end" string => escape(${section_end}); + + classes: + # Detect if section is already there + "has_$(csection)" expression => regline("${escaped_section_start}", "$(edit.filename)"); + + delete_lines: + ".*" + select_region => ncf_section_selector("${escaped_section_start}", "${escaped_section_end}"), + ifvarclass => "has_$(csection)"; + + insert_lines: + # Insert new, empty section if it doesn't exist already. + "${section_start} +${section_end}" + insert_type => "preserve_block", + ifvarclass => "!has_$(csection)"; + + # Insert missing lines or block into the section + "$(content)" + insert_type => "${insert_type}", + select_region => ncf_section_selector("${escaped_section_start}", "${escaped_section_end}"); +} + +# Enforce content in section. +# It will create the section if it does not exist yet. +# You can choose the insert_type: +# * Use "preserve_block" to insert blocks of text +# * Use "literal" to insert independant lines +# content_to_delete is a regexp to delete all lines (even outside section) matching the regex +bundle edit_line ncf_ensure_section_content_and_purge_type(section_start, section_end, content, insert_type, content_to_delete) +{ + vars: + "csection" string => canonify("$(section_start)"); + "escaped_section_start" string => escape(${section_start}); + "escaped_section_end" string => escape(${section_end}); + + classes: + # Detect if section is already there + "has_$(csection)" expression => regline("${escaped_section_start}", "$(edit.filename)"); + + "content_to_delete_defined" not => strcmp("${content_to_delete}", ""); + + any:: + "pass3" expression => "pass2"; + "pass2" expression => "pass1"; + "pass1" expression => "any"; + + + delete_lines: + ".*" + select_region => ncf_section_selector("${escaped_section_start}", "${escaped_section_end}"), + ifvarclass => "has_$(csection)"; + + !pass2:: + "${content_to_delete} .*" + ifvarclass => "content_to_delete_defined"; + + insert_lines: + # Insert new, empty section if it doesn't exist already. + "${section_start} +${section_end}" + insert_type => "preserve_block", + ifvarclass => "!has_$(csection)"; + + # Insert missing lines or block into the section + "$(content)" + insert_type => "${insert_type}", + select_region => ncf_section_selector("${escaped_section_start}", "${escaped_section_end}"); +} + + +# Ensure that a line is present in a section (INI-style) +# It will create the Section if it doesn't exist yet +bundle edit_line ensure_line_in_ini_section(section_name, line) +{ + insert_lines: + # If the section is not there, we need to insert it + "[${section_name}]" + comment => "Insert section if it doesn't exist"; + + "${line}" + select_region => INI_section("${section_name}"), + comment => "Insert line in section ${section_name}"; +} + +# Ensure that a line is present in an xml tag +# Won't create the tag if not there (we don't know where to put it) +bundle edit_line ensure_line_in_xml_tag(tag_name, line) +{ + vars: + "section_start" string => "\s*<${tag_name}>\s*"; + "section_end" string => "\s*\s*"; + + insert_lines: + "${line}" + select_region => ncf_section_selector("${section_start}", "${section_end}"), + comment => "Insert line in section ${tag_name}"; +} + +bundle edit_line prepend(lines) +{ + insert_lines: + "${lines}" + comment => "Prepending line: ${lines}", + location => start; +} + +bundle edit_line replace_line(regex, replacement) +{ + replace_patterns: + "${regex}" + replace_with => value("${replacement}"), + comment => "Replace every occurrence of ${regex} with ${replacement}"; +} + +bundle edit_line rudder_line_insertion(lines, location) +{ + insert_lines: + "${lines}" + comment => "Adding line: ${lines}", + location => rudder_location_before_after("${location}"); +} + +bundle edit_line edit_service_block_rc_d(service, action) +{ + insert_lines: +"if [ -x /etc/rc.d/rc.${service} ]; then + . /etc/rc.d/rc.${service} start +fi" + insert_type => "preserve_block"; +} + +bundle edit_line edit_service_block_shutdown(service) +{ + insert_lines: +"if [ -x /etc/rc.d/rc.${service} ]; then + . /etc/rc.d/rc.${service} stop +fi" + insert_type => "preserve_block"; +} + +# Edit AIX password file /etc/security/passwd +bundle edit_line ncf_ensure_AIX_password(username, password) +{ + vars: + "current_date" int => now(); + + classes: + # does the section exists, or should it be created ? + "section_absent" not => regline("${username}:", "${edit.filename}"); + + field_edits: + !section_absent:: + "\s*password\s*=.*" + # We need to put a space before password to keep the format password = + edit_field => col("=", "2", " ${password}", "set"), + select_region => ncf_section_AIX_user("${username}"); + + insert_lines: + section_absent:: + "${username}: + password = ${password} + lastupdate = ${current_date}" + insert_type => "preserve_block"; + +} + +# Define the lastupdate date when a password is changed +bundle edit_line ncf_edit_lastupdate_AIX_password(username) +{ + vars: + "current_date" int => now(); + + field_edits: + section_absent:: + "\s*lastupdate\s*=.*" + # We need to put a space before password to keep the format password = + edit_field => col("=", "2", " ${password}", "set"), + select_region => ncf_section_AIX_user("${username}"); + +} + +bundle edit_line rudder_change_aix_password_entry(user, entry, content) +{ + field_edits: + "\s*${entry}\s*=.*" + select_region => rudder_aix_user_section("${user}"), + edit_field => col("=","2"," ${content}","set"); +} + +bundle edit_line insert_rudder_disclaimer +{ + vars: + "file_edit_header" string => "${rudder_parameters.rudder_file_edit_header}"; + + defaults: + "file_edit_header" string => "############################################################# +### 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. ### +############################################################# +", + if_match_regex => "${const.dollar}{rudder_parameters.rudder_file_edit_header}"; + + insert_lines: + "${file_edit_header}" + location => start; +} + +# Add parameter in key->values line, where -> is key_value_separator +bundle edit_line ncf_add_parameter_in_list(key, key_value_separator, parameter_separator, parameter) +{ + vars: + "escaped_key" string => escape("${key}"); + + replace_patterns: + "^(${escaped_key}\s*${key_value_separator}\s*)(.*)$" + replace_with => ncf_add_parameter_with_separator("${parameter}", "${parameter_separator}"); +} + +# Add parameter in key->[values] line, where -> is key_value_separator and [ ] are leading and closing char separator +bundle edit_line ncf_add_parameter_in_list_with_enclosing_chars(key, key_value_separator, parameter_separator, parameter, leading_char_separator, closing_char_separator) +{ + vars: + "escaped_key" string => escape("${key}"); + "escaped_leading_char" string => escape("${leading_char_separator}"); + "escaped_closing_char" string => escape("${closing_char_separator}"); + + replace_patterns: + "^(${escaped_key}\s*${key_value_separator}\s*)(${escaped_leading_char})(.*)(${escaped_closing_char})\s*$" + replace_with => ncf_add_parameter_with_separator_and_enclosing_characters("${parameter}", "${parameter_separator}"); +} + +# Remove parameter_regex in key->[values] line, where -> is key_value_separator and [ ] are leading and closing char separator. Note: any whitespace between parameter_regex and parameter_separator will be also removed +bundle edit_line ncf_remove_parameter_in_list(key, key_value_separator, parameter_separator, parameter_regex, leading_char_separator, closing_char_separator) +{ + vars: + "escaped_key" string => escape("${key}"); + "escaped_leading_char" string => escape("${leading_char_separator}"); + "escaped_closing_char" string => escape("${closing_char_separator}"); + + replace_patterns: + "^(${escaped_key}\s*${key_value_separator}\s*${escaped_leading_char}.*)(${parameter_separator}+\s*${parameter_regex}|${parameter_regex}\s*${parameter_separator}+)(.*${escaped_closing_char})\s*$" + replace_with => value("${match.1}${match.3}"); +} + +bundle agent service_block_rc_d(service, new_class_prefix) +{ + vars: + "canon_service" string => canonify("${service}"); + + # When the dry run mode is enabled, the needed changes will not be applied, but the classes will be copied + files: + "/etc/rc.d/rc.local" + edit_line => edit_service_block_rc_d("${service}"), + classes => classes_generic("service_${canon_service}_block_in_rc_local"); + + "/etc/rc.d/rc.local_shutdown" + create => "true", + edit_line => edit_service_block_shutdown("${service}"), + classes => classes_generic("service_${canon_service}_block_in_rc_shutdown"); + + "/etc/rc.d/rc.M" + edit_line => edit_service_block_rc_d("${service}"), + classes => classes_generic("${class_prefix}"), + ifvarclass => "service_${canon_service}_block_in_rc_local_not_ok"; + + methods: + "combine" usebundle => ncf_classes_combine_two("service_${canon_service}_block_in_rc_local", "service_${canon_service}_block_in_rc_shutdown", "service_${canon_service}_block_in_rc_both"); + "new classes" usebundle => ncf_classes_copy("service_${service}_block_in_rc_both", "${class_prefix}"), + ifvarclass => "service_${canon_service}_block_in_rc_both_ok"; +} + +body replace_with ncf_add_parameter_with_separator(parameter, parameter_separator) +{ + occurrences => "first"; + replace_value => "${match.1}${match.2}${parameter_separator}${parameter}"; +} + +body replace_with ncf_add_parameter_with_separator_and_enclosing_characters(parameter, parameter_separator) +{ + occurrences => "first"; + replace_value => "${match.1}${match.2}${match.3}${parameter_separator}${parameter}${match.4}"; +} + +# DEPRECATED - for compatibility +body delete_select rudder_delete_if_not_in_list(lines_to_delete) +{ + delete_if_not_match_from_list => { @{lines_to_delete} }; +} + +# Select lines for deletion +# Select the lines that are not in the list (complete line match) +body delete_select ncf_delete_if_not_in_list(lines_to_delete) +{ + delete_if_not_match_from_list => { @{lines_to_delete} }; +} + +body select_region ncf_section_selector(section_start, section_end) +{ + select_start => "${section_start}"; + select_end => "${section_end}"; +} + +# DEPRECATED - for compatibility +body select_region rudder_section_selector(section_start, section_end) +{ + select_start => "${section_start}"; + select_end => "${section_end}"; +} + +# Select region in /etc/security/passwd file +body select_region ncf_section_AIX_user(username) +{ + select_start => "${username}:"; + select_end => ".*:"; +} + +body select_region rudder_aix_user_section(x) +{ + select_start => "${x}:\s*"; + select_end => "\S*:\s*"; +} + +# Enforce or not content of a file +######################################################################## +# Same as std_defs, allowing user to specify the file erase policy # +######################################################################## +body edit_defaults ncf_empty_select(select) +{ + empty_file_before_editing => "${select}"; + max_file_size => "25M"; + edit_backup => "timestamp"; +} + +# DEPRECATED +body edit_defaults rudder_empty_select(select) +{ + inherit_from => ncf_empty_select("${select}"); +} + +body edit_defaults empty_size(size) +{ + empty_file_before_editing => "true"; + edit_backup => "false"; + max_file_size => "${size}"; +} + +# DEPRECATED +body edit_defaults noempty_backup +{ + inherit_from => ncf_empty_select("false"); +} + +# DEPRECATED +body edit_defaults empty_backup +{ + inherit_from => ncf_empty_select("true"); +} + +body location rudder_location_before_after(location) +{ + before_after => "${location}"; +} + +# Modular local copy_from body +body copy_from ncf_local_cp_method(from, method) +{ + source => "${from}"; + compare => "${method}"; + copy_backup => "timestamp"; +} + +# Modular remote copy_from body +# This body gets the CFEngine port from ncf's configuration. +body copy_from ncf_remote_cp_method(from, server, method) +{ + servers => { "${server}" }; + source => "${from}"; + portnumber => "${configuration.cfengine_port}"; + compare => "${method}"; + encrypt => "true"; + copy_backup => "timestamp"; +} + +# DEPRECATED +#server may be a list +body copy_from cp(from,server) +{ + servers => { "${server}" }; + source => "${from}"; + compare => "digest"; + + community_edition:: + portnumber => "${system_common.community_port}"; +} + +# DEPRECATED +# 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"; + servers => { "${server}" }; + + community_edition:: + portnumber => "${system_common.community_port}"; +} + +body copy_from copy(from) +{ + source => "${from}"; + copy_backup => "false"; + preserve => "true"; +} + +# DEPRECATED +body copy_from copy_digest(from) +{ + source => "${from}"; + copy_backup => "timestamp"; + preserve => "true"; + compare => "digest"; +} + +body copy_from digest_cp(from) +{ + source => "${from}"; + copy_backup => "timestamp"; + compare => "digest"; + copylink_patterns => { ".*" }; +} + +# DEPRECATED +body perms u_p(p) +{ + inherit_from => m("${p}"); +} + +################################################ +# Simple group adjustment body +################################################ +body perms group(group) +{ + groups => { "${group}" }; +} + +######################################################################## +# Change group and mode of a file/directory # +######################################################################## +body perms mg(mode,group) +{ + groups => { "${group}" }; + mode => "${mode}"; +} + +bundle agent perm_on_file(file, mod, class_prefix) +{ + vars: + "canonfile" string => canonify("${file}"); + + files: + "${file}" + perms => m("${mod}"), + classes => classes_generic("${class_prefix}"); +} + +body depth_search recurse_visible(d) +{ + depth => "${d}"; + exclude_dirs => { "\..*" }; +} + +######################################################################## +# Handle a directory recursively, including the dir itself # +######################################################################## +body depth_search recurse_withroot(d) +{ + depth => "${d}"; + include_basedir => "true"; +} + +################################################ +# 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"; +} + +# +# Select files older than X months +# +body file_select ncf_months_old(months) +{ + mtime => irange(0,ago(0,"${months}",0,0,0,0)); + file_result => "mtime"; +} + +# +# Select files older than X hours +# +body file_select ncf_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 ncf_minutes_old(minutes) +{ + mtime => irange(0,ago(0,0,0,0,"${minutes}",0)); + file_result => "mtime"; +} + +# DEPRECATED - for compatibility +body file_select rudder_common_minutes_old(minutes) +{ + mtime => irange(0,ago(0,0,0,0,"${minutes}",0)); + file_result => "mtime"; +} + +######################################################################## +# 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"; +} diff --git a/tree/20_cfe_basics/flag_lib.cf b/tree/20_cfe_basics/flags.cf similarity index 98% rename from tree/20_cfe_basics/flag_lib.cf rename to tree/20_cfe_basics/flags.cf index 7a66ca592..fca5698d1 100644 --- a/tree/20_cfe_basics/flag_lib.cf +++ b/tree/20_cfe_basics/flags.cf @@ -88,13 +88,15 @@ # # This is called in 10_ncf_internals/initialization.cf -bundle agent flag_initialization { +bundle agent flag_initialization +{ vars: # designed to be incremented when a global unique ID is needed "flag_unique.value" string => "1"; } -bundle agent cancel_flag(name) { +bundle agent cancel_flag(name) +{ vars: "cname" string => canonify("${name}"); "cancel" string => "", @@ -102,7 +104,8 @@ bundle agent cancel_flag(name) { if => "flag_reserved_${cname}" ; } -bundle agent reserve_flag(name) { +bundle agent reserve_flag(name) +{ vars: "cname" string => canonify("${name}"); "flag_unique.value" string => eval("${flag_unique.value}+1", "math", "infix"); @@ -155,7 +158,8 @@ bundle agent reserve_flag(name) { if => "reserved"; } -bundle agent set_flag(name) { +bundle agent set_flag(name) +{ vars: "cname" string => canonify("${name}"); "time" string => strftime("localtime", "%FT%T%z", "${sys.systime}"); @@ -218,7 +222,8 @@ bundle agent set_flag(name) { # Should probably not be necessary, unless you need to know the state of the flag # without reserving it -bundle agent get_flag(name) { +bundle agent get_flag(name) +{ vars: "cname" string => canonify("${name}"); "flag_unique.value" string => eval("${flag_unique.value}+1", "math", "infix"); @@ -260,7 +265,8 @@ bundle agent get_flag(name) { } # This updates the value of the in-memory flags database. Should not be called from outside. -bundle agent _read_flags { +bundle agent _read_flags +{ vars: "flag_unique.value" string => eval("${flag_unique.value}+1", "math", "infix"); @@ -278,4 +284,3 @@ bundle agent _read_flags { "pass2" expression => "pass1"; "pass1" expression => "any"; } - diff --git a/tree/20_cfe_basics/log_rudder.cf b/tree/20_cfe_basics/log_rudder.cf index f7beb6d41..434bf16fe 100644 --- a/tree/20_cfe_basics/log_rudder.cf +++ b/tree/20_cfe_basics/log_rudder.cf @@ -16,7 +16,6 @@ # ##################################################################################### - # @name Log for Rudder # @description Logging output for Rudder reports # @@ -31,9 +30,7 @@ bundle agent log_rudder(message, class_parameter, old_class_prefix, class_prefix, args) { - vars: - "c_old_class_prefix" string => canonify("${old_class_prefix}"); # When ${class_prefix} itself contains ${class_prefix}, it uses the previous value when calling # _rudder_common_reports_generic. We reset it at the beginning of the bundle execution @@ -78,6 +75,29 @@ bundle agent log_rudder(message, class_parameter, old_class_prefix, class_prefix "${configuration.info}: Class prefix is too long - fallbacking to old_class_prefix ${old_class_prefix} for reporting"; } +# @name Logger for Rudder - legacy interface (DEPRECATED) +# @deprecated Use [log_rudder](#log_rudder) instead. +# @description Logging output for Rudder reports. This interface is for compatiblity with older generic methods and techniques, and is replaced by log_rudder. +# +# @parameter message The common part of the message to display +# @parameter old_class_prefix The prefix of the class for different states (0.x version, empty to force new style logging only) +# +# @class_prefix logger_rudder +# @class_parameter old_class_prefix + +bundle agent logger_rudder(message, old_class_prefix) +{ + vars: + "empty_slist" slist => { cf_null }; + + methods: + "legacy logger_rudder wrapper" usebundle => log_rudder("${message}", "", "${old_class_prefix}", "", @{empty_slist}); + + reports: + cfengine:: + "WARNING: DEPRECATED logger_rudder interface called. Please use log_rudder instead (${old_class_prefix}: ${message})"; +} + # bundle backported from rudder (prefixed with _ to avoid conflicts) # all this would be removed when we put this file back to rudder # @@ -214,14 +234,12 @@ bundle agent _rudder_common_reports_generic(technique_name, class_prefix, identi ifvarclass => "${class_prefix}_repaired"; } - ###################################################################### ##### Reporting for the pre/post hooks ##### These methods should not be used for normal generic method usage ##### because they do not respect the stop on repair for audit mode ###################################################################### -# # Automatically create reports based on existing classes starting by # class_prefix (as defined by the body classes rudder_common_classes) # Difference with _rudder_common_reports_generic : it remaps _repaired @@ -354,13 +372,15 @@ bundle agent _rudder_common_report_hooks(technique_name, status, identifier, com # # Define the current Technique we are doing report on # Must be called before the reporting -bundle agent _method_reporting_context(c_name, c_key) { +bundle agent _method_reporting_context(c_name, c_key) +{ vars: "report_data.component_name" string => "${c_name}"; "report_data.component_key" string => "${c_key}" ; } -bundle agent rudder_reporting_context(d_id, r_id, t_name) { +bundle agent rudder_reporting_context(d_id, r_id, t_name) +{ vars: "report_data.technique_name" string => "${t_name}"; "report_data.directive_id" string => "${d_id}"; @@ -368,14 +388,15 @@ bundle agent rudder_reporting_context(d_id, r_id, t_name) { "report_data.identifier" string => "${r_id}@@${d_id}@@0"; } - -bundle agent rudder_reporting_context_id(id, t_name) { +bundle agent rudder_reporting_context_id(id, t_name) +{ vars: "report_data.technique_name" string => "${t_name}"; "report_data.identifier" string => "${id}"; } -bundle agent clean_reporting_context { +bundle agent clean_reporting_context +{ vars: "report_data.component_name" string => ""; "report_data.component_key" string => ""; @@ -385,37 +406,29 @@ bundle agent clean_reporting_context { "report_data.identifier" string => ""; } -bundle agent disable_reporting { +bundle agent disable_reporting +{ vars: "report_data.should_report" string => "false"; } -bundle agent enable_reporting { +bundle agent enable_reporting +{ vars: "report_data.should_report" string => "true"; } - - - -##################################################################### - - - - - - # # Automatically defines classes bases on a given prefix # The classes are defined based on the promises outcome # body classes rudder_common_classes(prefix) { - promise_kept => { "${prefix}_kept" , "${prefix}_ok" }; - promise_repaired => { "${prefix}_repaired", "${prefix}_ok" }; - repair_failed => { "${prefix}_failed" , "${prefix}_error" }; - repair_denied => { "${prefix}_denied" , "${prefix}_error" }; - repair_timeout => { "${prefix}_timeout" , "${prefix}_error" }; + promise_kept => { "${prefix}_kept" , "${prefix}_ok" }; + promise_repaired => { "${prefix}_repaired", "${prefix}_ok" }; + repair_failed => { "${prefix}_failed" , "${prefix}_error" }; + repair_denied => { "${prefix}_denied" , "${prefix}_error" }; + repair_timeout => { "${prefix}_timeout" , "${prefix}_error" }; } # @@ -425,13 +438,13 @@ body classes rudder_common_classes(prefix) # body classes rudder_common_classes_persist(prefix, persist) { - promise_kept => { "${prefix}_kept" , "${prefix}_ok" }; - promise_repaired => { "${prefix}_repaired", "${prefix}_ok" }; - repair_failed => { "${prefix}_failed" , "${prefix}_error" }; - repair_denied => { "${prefix}_denied" , "${prefix}_error" }; - repair_timeout => { "${prefix}_timeout" , "${prefix}_error" }; + promise_kept => { "${prefix}_kept" , "${prefix}_ok" }; + promise_repaired => { "${prefix}_repaired", "${prefix}_ok" }; + repair_failed => { "${prefix}_failed" , "${prefix}_error" }; + repair_denied => { "${prefix}_denied" , "${prefix}_error" }; + repair_timeout => { "${prefix}_timeout" , "${prefix}_error" }; - persist_time => ${persist}; + persist_time => ${persist}; } # @@ -440,19 +453,19 @@ body classes rudder_common_classes_persist(prefix, persist) # body classes rudder_always_classes_persist(always, persist) { - promise_kept => { "${always}" }; - promise_repaired => { "${always}" }; - repair_failed => { "${always}" }; - repair_denied => { "${always}" }; - repair_timeout => { "${always}" }; + promise_kept => { "${always}" }; + promise_repaired => { "${always}" }; + repair_failed => { "${always}" }; + repair_denied => { "${always}" }; + repair_timeout => { "${always}" }; - persist_time => "${persist}"; + persist_time => "${persist}"; } # DEPRECATED - for compatibility body classes _rudder_always_classes_persist(always, persist) { - inherit_from => rudder_always_classes_persist("${always}", "${persist}"); + inherit_from => rudder_always_classes_persist("${always}", "${persist}"); } ################################################ @@ -481,7 +494,7 @@ body classes _rudder_always_classes_persist(always, persist) bundle agent rudder_common_report(technique_name, status, identifier, component_name, component_key, message) { methods: - "report" usebundle => rudder_common_report_index("${technique_name}", "${status}", "${identifier}", "${component_name}", "${component_key}", "${message}", ""); + "report" usebundle => rudder_common_report_index("${technique_name}", "${status}", "${identifier}", "${component_name}", "${component_key}", "${message}", ""); } # @@ -556,8 +569,6 @@ bundle agent rudder_common_report_index(technique_name, status, identifier, comp comment => "Reporting for ${technique_name} message ${message} for index ${index}"; } - -# # Automatically create reports based on existing classes starting by # class_prefix (as defined by the body classes rudder_common_classes) # Takes 6 parameters diff --git a/tree/20_cfe_basics/logger_rudder.cf b/tree/20_cfe_basics/logger_rudder.cf deleted file mode 100644 index 55e411b57..000000000 --- a/tree/20_cfe_basics/logger_rudder.cf +++ /dev/null @@ -1,43 +0,0 @@ -##################################################################################### -# Copyright 2015 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 . -# -##################################################################################### - -# @name Logger for Rudder - legacy interface (DEPRECATED) -# @deprecated Use [log_rudder](#log_rudder) instead. -# @description Logging output for Rudder reports. This interface is for compatiblity with older generic methods and techniques, and is replaced by log_rudder. -# -# @parameter message The common part of the message to display -# @parameter old_class_prefix The prefix of the class for different states (0.x version, empty to force new style logging only) -# -# @class_prefix logger_rudder -# @class_parameter old_class_prefix - -bundle agent logger_rudder(message, old_class_prefix) -{ - - vars: - "empty_slist" slist => { cf_null }; - - methods: - "legacy logger_rudder wrapper" usebundle => log_rudder("${message}", "", "${old_class_prefix}", "", @{empty_slist}); - - - reports: - cfengine:: - "WARNING: DEPRECATED logger_rudder interface called. Please use log_rudder instead (${old_class_prefix}: ${message})"; - -} diff --git a/tree/20_cfe_basics/ncf_lib.cf b/tree/20_cfe_basics/ncf_lib.cf deleted file mode 100644 index 61ada7dc6..000000000 --- a/tree/20_cfe_basics/ncf_lib.cf +++ /dev/null @@ -1,1954 +0,0 @@ -##################################################################################### -# Copyright 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 . -# -##################################################################################### - -# Constants definitions -bundle common ncf_const { - vars: - "s" string => " "; -} - - -# Use rudder_curl variable if available, rather than the path[curl] -bundle common ncf_paths { - vars: - "path[curl]" string => "${g.rudder_curl}", - if => isvariable("g.rudder_curl"); - - "path[curl]" string => "${paths.path[curl]}", - unless => isvariable("g.rudder_curl"); - - - "all_paths" slist => getindices("path"); - "$(all_paths)" string => "$(path[$(all_paths)])"; - - classes: - "_ncf_path_exists_$(all_paths)" - expression => fileexists("$(path[$(all_paths)])"), - comment => "It's useful to know if $(all_paths) exists on the filesystem as defined"; - -} - -# DEPRECATED -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}'"; - -} - -# DEPRECATED -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}'"; - -} - -# DEPRECATED -body package_method yum_rpm_no_version -{ - package_changes => "bulk"; - package_list_command => "/bin/rpm -qa --qf '%{name}.%{arch} %{version}-%{release}\n'"; - package_patch_list_command => "/usr/bin/yum ${redhat_knowledge.yum_options} check-update"; - - package_list_name_regex => "([^.]+).*"; - package_list_version_regex => "[^\s]\s+([^\s]+).*"; - package_list_arch_regex => "[^.]+\.([^\s]+).*"; - - package_installed_regex => ".*"; - package_name_convention => "$(name)"; - - # just give the package name to rpm to delete, otherwise it gets "name.*" (from package_name_convention above) - package_delete_convention => "$(name)"; - - # set it to "0" to avoid caching of list during upgrade - package_list_update_command => "/usr/bin/yum ${redhat_knowledge.yum_options} check-update"; - 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 => "$(redhat_knowledge.call_yum) $(redhat_knowledge.yum_options) -y install"; - package_update_command => "$(redhat_knowledge.call_yum) $(redhat_knowledge.yum_options) -y update"; - package_patch_command => "$(redhat_knowledge.call_yum) $(redhat_knowledge.yum_options) -y update"; - package_delete_command => "$(rpm_knowledge.call_rpm) -e --nodeps"; - package_verify_command => "$(rpm_knowledge.call_rpm) -V"; - package_noverify_returncode => "1"; - package_version_less_command => "$(redhat_knowledge.rpm_compare_less)"; - package_version_equal_command => "$(redhat_knowledge.rpm_compare_equal)"; -} - - -# Install packages using yum localinstall, disable package caching -# DEPRECATED -body package_method redhat_local_install -{ -redhat:: - package_changes => "bulk"; - package_list_command => "/bin/rpm -qa --qf '%{name} %{version}-%{release} %{arch}\n'"; - package_patch_list_command => "/usr/bin/yum ${redhat_knowledge.yum_options} 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_command => "/usr/bin/yum ${redhat_knowledge.yum_options} check-update"; - 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 ${redhat_knowledge.yum_options} -y localinstall"; - package_update_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; - package_patch_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; - package_delete_command => "/bin/rpm -e --nodeps --allmatches"; - package_verify_command => "/bin/rpm -V"; - package_noverify_returncode => "1"; - package_version_less_command => "$(redhat_knowledge.rpm_compare_less)"; - package_version_equal_command => "$(redhat_knowledge.rpm_compare_equal)"; -} -# Install packages using yum standard install, disable package caching -# DEPRECATED -body package_method redhat_install -{ -redhat:: - package_changes => "bulk"; - package_list_command => "/bin/rpm -qa --qf '%{name} %{version}-%{release} %{arch}\n'"; - package_patch_list_command => "/usr/bin/yum ${redhat_knowledge.yum_options} 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_command => "/usr/bin/yum ${redhat_knowledge.yum_options} check-update"; - 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 ${redhat_knowledge.yum_options} -y install"; - package_update_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; - package_patch_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; - package_delete_command => "/bin/rpm -e --nodeps --allmatches"; - package_verify_command => "/bin/rpm -V"; - package_noverify_returncode => "1"; - package_version_less_command => "$(redhat_knowledge.rpm_compare_less)"; - package_version_equal_command => "$(redhat_knowledge.rpm_compare_equal)"; -} - -# DEPRECATED -body package_method debian_local_install -{ - package_changes => "individual"; - package_list_command => "$(debian_knowledge.call_dpkg) -l"; - # set it to "0" to avoid caching of list during upgrade - package_list_update_command => "$(debian_knowledge.call_apt_get) update"; - package_list_update_ifelapsed => "0"; - 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)" }; - package_add_command => "$(debian_knowledge.call_dpkg) --install"; - package_delete_command => "$(debian_knowledge.call_dpkg) --purge"; - package_update_command => "$(debian_knowledge.call_dpkg) --install"; - package_patch_command => "$(debian_knowledge.call_dpkg) --install"; - - # make correct version comparisons - package_version_less_command => "$(debian_knowledge.dpkg_compare_less)"; - package_version_equal_command => "$(debian_knowledge.dpkg_compare_equal)"; - -x86_64:: - package_name_convention => "$(name)_$(version)_amd64.deb"; -i686:: - package_name_convention => "$(name)_$(version)_i386.deb"; -have_aptitude:: - package_patch_list_command => "/usr/bin/aptitude --assume-yes --simulate --verbose full-upgrade"; - package_patch_name_regex => "^Inst\s+(\S+)\s+.*"; - package_patch_version_regex => "^Inst\s+\S+\s+\[?\(?([^\],\s]+).*"; -!have_aptitude:: - package_patch_list_command => "$(debian_knowledge.call_apt_get) --just-print dist-upgrade"; - package_patch_name_regex => "^Inst\s+(\S+)\s+.*"; - package_patch_version_regex => "^Inst\s+\S+\s+\[?\(?([^\],\s]+).*"; -} - -# DEPRECATED -body package_method ncf_generic -{ -SuSE:: - 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_command => "/usr/bin/zypper --non-interactive refresh"; - package_list_update_ifelapsed => "240"; # 4 hours - package_installed_regex => "i.*"; - package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*"; - package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; - package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; - 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 ${redhat_knowledge.yum_options} 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_command => "/usr/bin/yum ${redhat_knowledge.yum_options} check-update"; - 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 ${redhat_knowledge.yum_options} -y install"; - package_update_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; - package_patch_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; - package_delete_command => "/bin/rpm -e --nodeps --allmatches"; - package_verify_command => "/bin/rpm -V"; - package_version_less_command => "$(redhat_knowledge.rpm_compare_less)"; - package_version_equal_command => "$(redhat_knowledge.rpm_compare_equal)"; - -debian:: - package_changes => "bulk"; - package_list_command => "$(debian_knowledge.call_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 - - # make correct version comparisons - package_version_less_command => "$(debian_knowledge.dpkg_compare_less)"; - package_version_equal_command => "$(debian_knowledge.dpkg_compare_equal)"; - - -debian.have_aptitude:: - package_add_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes install"; - package_list_update_command => "/usr/bin/aptitude update"; - package_delete_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes remove"; - package_update_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes install"; - package_patch_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes install"; - package_verify_command => "/usr/bin/aptitude show"; - package_noverify_regex => "(State: not installed|E: Unable to locate package .*)"; - - package_patch_list_command => "/usr/bin/aptitude --assume-yes --simulate --verbose full-upgrade"; - package_patch_name_regex => "^Inst\s+(\S+)\s+.*"; - package_patch_version_regex => "^Inst\s+\S+\s+\[?\(?([^\],\s]+).*"; - -debian.!have_aptitude:: - package_add_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; - package_list_update_command => "$(debian_knowledge.call_apt_get) update"; - package_delete_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes remove"; - package_update_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; - package_patch_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; - package_verify_command => "$(debian_knowledge.call_dpkg) -s"; - package_noverify_returncode => "1"; - - package_patch_list_command => "$(debian_knowledge.call_apt_get) --just-print dist-upgrade"; - package_patch_name_regex => "^Inst\s+(\S+)\s+.*"; - package_patch_version_regex => "^Inst\s+\S+\s+\[?\(?([^\],\s]+).*"; - -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"; - -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"; - -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).*"; - -archlinux:: - package_changes => "bulk"; - package_list_command => "/usr/bin/pacman -Q"; - package_list_name_regex => "(.*)\s+.*"; - package_list_version_regex => ".*\s+(.*)"; - package_installed_regex => ".*"; - package_name_convention => "$(name)"; - package_list_update_ifelapsed => "240"; - 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"; -} - -# Same as ncf_generic with version in package name -# DEPRECATED -body package_method ncf_generic_version -{ - SuSE:: - 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_command => "/usr/bin/zypper --non-interactive refresh"; - package_list_update_ifelapsed => "240"; # 4 hours - package_installed_regex => "i.*"; - package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*"; - package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; - package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; - package_patch_name_regex => "[^|]+\|\s+([^\s]+).*"; - package_patch_version_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*"; - package_name_convention => "$(name)=$(version)"; - 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 ${redhat_knowledge.yum_options} 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)-$(version)"; - package_list_update_command => "/usr/bin/yum ${redhat_knowledge.yum_options} check-update"; - 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 ${redhat_knowledge.yum_options} -y install"; - package_update_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; - package_patch_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; - package_delete_command => "/bin/rpm -e --nodeps --allmatches"; - package_verify_command => "/bin/rpm -V"; - package_version_less_command => "$(redhat_knowledge.rpm_compare_less)"; - package_version_equal_command => "$(redhat_knowledge.rpm_compare_equal)"; - - debian:: - package_changes => "bulk"; - package_list_command => "$(debian_knowledge.call_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)=$(version)"; - package_list_update_ifelapsed => "240"; # 4 hours - - # make correct version comparisons - package_version_less_command => "$(debian_knowledge.dpkg_compare_less)"; - package_version_equal_command => "$(debian_knowledge.dpkg_compare_equal)"; - - - debian.have_aptitude:: - package_add_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes install"; - package_list_update_command => "/usr/bin/aptitude update"; - package_delete_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes remove"; - package_update_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes install"; - package_patch_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes install"; - package_verify_command => "/usr/bin/aptitude show"; - package_noverify_regex => "(State: not installed|E: Unable to locate package .*)"; - - package_patch_list_command => "/usr/bin/aptitude --assume-yes --simulate --verbose full-upgrade"; - package_patch_name_regex => "^Inst\s+(\S+)\s+.*"; - package_patch_version_regex => "^Inst\s+\S+\s+\[?\(?([^\],\s]+).*"; - - debian.!have_aptitude:: - package_add_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; - package_list_update_command => "$(debian_knowledge.call_apt_get) update"; - package_delete_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes remove"; - package_update_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; - package_patch_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; - package_verify_command => "$(debian_knowledge.call_dpkg) -s"; - package_noverify_returncode => "1"; - - package_patch_list_command => "$(debian_knowledge.call_apt_get) --just-print dist-upgrade"; - package_patch_name_regex => "^Inst\s+(\S+)\s+.*"; - package_patch_version_regex => "^Inst\s+\S+\s+\[?\(?([^\],\s]+).*"; - - 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"; - - 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)=$(version)"; - package_add_command => "/sbin/apk add"; - package_delete_command => "/sbin/apk del"; - - 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).*"; - - archlinux:: - package_changes => "bulk"; - package_list_command => "/usr/bin/pacman -Q"; - package_list_name_regex => "(.*)\s+.*"; - package_list_version_regex => ".*\s+(.*)"; - package_installed_regex => ".*"; - package_name_convention => "$(name)"; - package_list_update_ifelapsed => "240"; - 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"; -} - -# Same as apt_get from CFEngine lib with version in package name -# DEPRECATED -body package_method apt_get_version -{ - package_changes => "bulk"; - package_list_command => "$(debian_knowledge.call_dpkg) -l"; - package_list_name_regex => "$(debian_knowledge.list_name_regex)"; - package_list_version_regex => "$(debian_knowledge.list_version_regex)"; - package_installed_regex => ".i.*"; # packages that have been uninstalled may be listed - package_name_convention => "$(name)=$(version)"; - - # set it to "0" to avoid caching of list during upgrade - package_list_update_ifelapsed => "$(common_knowledge.list_update_ifelapsed)"; - - # Target a specific release, such as backports - package_add_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; - package_list_update_command => "$(debian_knowledge.call_apt_get) update"; - package_delete_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes -q remove"; - package_update_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; - package_patch_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; - package_verify_command => "$(debian_knowledge.call_dpkg) -s"; - package_noverify_returncode => "1"; - - package_patch_list_command => "$(debian_knowledge.call_apt_get) --just-print dist-upgrade"; - package_patch_name_regex => "$(debian_knowledge.patch_name_regex)"; - package_patch_version_regex => "$(debian_knowledge.patch_version_regex)"; - - # make correct version comparisons - package_version_less_command => "$(debian_knowledge.dpkg_compare_less)"; - package_version_equal_command => "$(debian_knowledge.dpkg_compare_equal)"; -} - -######################################################################## -# Install a package using rug # -######################################################################## -# DEPRECATED -body package_method rudder_rug -{ - - package_changes => "individual"; - - package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\""; - 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_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"; - - 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 # -######################################################################## -# DEPRECATED -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 ${redhat_knowledge.yum_options} 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 ${redhat_knowledge.yum_options} -y install"; - package_update_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; - package_patch_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -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}"; - -} - -# Don't do anything if class warn is defined, or remediate the promises -# if immediate is defined (default action) -# DEPRECATED: warn and immediate need to be global classes, use policy(p) instead. -body action do_if_immediate { - warn|dry_run|global_dry_run:: - action_policy => "warn"; -} - -# Useful for immediate call to bundles with dry-run mode on, -# as we do not want dry-run mode applied on it. -body action immediate_ignore_dry_run -{ - ifelapsed => "0"; -} - -body action WarnOnly -{ - action_policy => "warn"; -} - -body contain outputable -{ - useshell => "true"; - no_output => "false"; -} - -body depth_search recurse_visible(d) -{ - depth => "${d}"; - exclude_dirs => { "\..*" }; -} - -######################################################################## -# Handle a directory recursively, including the dir itself # -######################################################################## -body depth_search recurse_withroot(d) -{ - depth => "${d}"; - include_basedir => "true"; -} - -################################################ -# 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"; -} - -bundle edit_line ncf_insert_block(block) { - insert_lines: - "${block}" - insert_type => "preserve_block", - comment => "Append a text block if it does not exist"; -} - -# Sets the RHS of configuration items with a given separator -# supports keys that contains special characters (like *, ?) -# This bundle will allow any quantity of spaces before the separator, but none -# between the separator and the value -bundle edit_line ncf_maintain_keys_values(v, sep) { - vars: - "index" slist => getindices("${v}"); - # Be careful if the index string contains funny chars - "cindex[${index}]" string => canonify("${index}"); - - # Keys and values may contain regexps. Escape them for replace_pattern matching. - "ve[${index}]" string => escape("${${v}[${index}]}"); - "ke[${index}]" string => escape("${index}"); - "separator" string => escape("${sep}"); - - # Matching pattern for line (basically key-and-separator) - "keypat[${index}]" string => "\s*${ke[${index}]}\s*${separator}\s*"; - - classes: - "${cindex[${index}]}_key_in_file" - comment => "Dynamic Class created if patterns matching", - expression => regline("^${keypat[${index}]}.*", "${edit.filename}"); - - insert_lines: - "${index}${sep}${${v}[${index}]}" - comment => "Insert definition of ${index}", - ifvarclass => "!${cindex[${index}]}_key_in_file"; - - 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}]}"); - -} - -# Sets the RHS of configuration items with a given separator -# supports keys that contains special characters (like *, ?), with option to be strict or not -# by default, treat non strictly spacing. If option is "strict", then no space will be allowed -bundle edit_line ncf_maintain_keys_values_option(v, sep, option) { - vars: - "index" slist => getindices("${v}"); - # Be careful if the index string contains funny chars - "cindex[${index}]" string => canonify("${index}"); - - # Keys and values may contain regexps. Escape them for replace_pattern matching. - "ve[${index}]" string => escape("${${v}[${index}]}"); - "ke[${index}]" string => escape("${index}"); - "separator" string => escape("${sep}"); - - # Matching pattern for line (basically key-and-separator) - "keypat[${index}]" string => "\s*${ke[${index}]}\s*${separator}\s*"; - - - classes: - "strict_spacing" expression => strcmp("${option}", "strict"); - - "${cindex[${index}]}_key_in_file" - comment => "Dynamic Class created if patterns matching", - expression => regline("^${keypat[${index}]}.*", "${edit.filename}"); - - !strict_spacing:: - "${cindex[${index}]}_key_value_in_file" - comment => "Dynamic Class created if in loose mode, key\s*separator\s*value is there", - expression => regline("^${keypat[${index}]}${ve[${index}]}\s*", "${edit.filename}"); - - - insert_lines: - "${index}${sep}${${v}[${index}]}" - comment => "Insert definition of ${index}", - ifvarclass => "!${cindex[${index}]}_key_in_file"; - - replace_patterns: - # For convergence need to use negative lookahead on value: - # "key sep (?!value).*" - strict_spacing:: - "^(\s*${ke[${index}]}\s*${separator}\s*)(?!${ve[${index}]}$).*" - comment => "Strict replace definition of ${index}", - replace_with => value("${ke[${index}]}${sep}${${v}[${index}]}"); - - !strict_spacing:: - "^(\s*${ke[${index}]}\s*${separator}\s*)(?!${ve[${index}]}$).*" - comment => "Replace definition of ${index}", - replace_with => value("${match.1}${${v}[${index}]}"), - ifvarclass => "!${cindex[${index}]}_key_value_in_file"; - -} - -# enforce lines in section -# WARNING: This bundle is deprecated and will be removed. -# You should use ncf_ensure_section_content_type with the "literal" insert type. -bundle edit_line ncf_ensure_section_content(section_start, section_end, content) -{ - vars: - "csection" string => canonify("$(section_start)"); - "escaped_section_start" string => escape(${section_start}); - "escaped_section_end" string => escape(${section_end}); - - classes: - # Detect if section is already there - "has_$(csection)" expression => regline("${escaped_section_start}", "$(edit.filename)"); - - delete_lines: - ".*" - select_region => ncf_section_selector("${escaped_section_start}", "${escaped_section_end}"), - ifvarclass => "has_$(csection)"; - - insert_lines: - # Insert new, empty section if it doesn't exist already. - "${section_start} -${section_end}" - insert_type => "preserve_block", - ifvarclass => "!has_$(csection)"; - - # Insert missing lines into the section - "$(content)" - select_region => ncf_section_selector("${escaped_section_start}", "${escaped_section_end}"); -} - -# Enforce content in section. -# It will create the section if it does not exist yet. -# You can choose the insert_type: -# * Use "preserve_block" to insert blocks of text -# * Use "literal" to insert independant lines -bundle edit_line ncf_ensure_section_content_type(section_start, section_end, content, insert_type) -{ - vars: - "csection" string => canonify("$(section_start)"); - "escaped_section_start" string => escape(${section_start}); - "escaped_section_end" string => escape(${section_end}); - - classes: - # Detect if section is already there - "has_$(csection)" expression => regline("${escaped_section_start}", "$(edit.filename)"); - - delete_lines: - ".*" - select_region => ncf_section_selector("${escaped_section_start}", "${escaped_section_end}"), - ifvarclass => "has_$(csection)"; - - insert_lines: - # Insert new, empty section if it doesn't exist already. - "${section_start} -${section_end}" - insert_type => "preserve_block", - ifvarclass => "!has_$(csection)"; - - # Insert missing lines or block into the section - "$(content)" - insert_type => "${insert_type}", - select_region => ncf_section_selector("${escaped_section_start}", "${escaped_section_end}"); -} - - -# Enforce content in section. -# It will create the section if it does not exist yet. -# You can choose the insert_type: -# * Use "preserve_block" to insert blocks of text -# * Use "literal" to insert independant lines -# content_to_delete is a regexp to delete all lines (even outside section) matching the regex -bundle edit_line ncf_ensure_section_content_and_purge_type(section_start, section_end, content, insert_type, content_to_delete) -{ - vars: - "csection" string => canonify("$(section_start)"); - "escaped_section_start" string => escape(${section_start}); - "escaped_section_end" string => escape(${section_end}); - - classes: - # Detect if section is already there - "has_$(csection)" expression => regline("${escaped_section_start}", "$(edit.filename)"); - - "content_to_delete_defined" not => strcmp("${content_to_delete}", ""); - - any:: - "pass3" expression => "pass2"; - "pass2" expression => "pass1"; - "pass1" expression => "any"; - - - delete_lines: - ".*" - select_region => ncf_section_selector("${escaped_section_start}", "${escaped_section_end}"), - ifvarclass => "has_$(csection)"; - - !pass2:: - "${content_to_delete} .*" - ifvarclass => "content_to_delete_defined"; - - insert_lines: - # Insert new, empty section if it doesn't exist already. - "${section_start} -${section_end}" - insert_type => "preserve_block", - ifvarclass => "!has_$(csection)"; - - # Insert missing lines or block into the section - "$(content)" - insert_type => "${insert_type}", - select_region => ncf_section_selector("${escaped_section_start}", "${escaped_section_end}"); -} - - -# Ensure that a line is present in a section (INI-style) -# It will create the Section if it doesn't exist yet -bundle edit_line ensure_line_in_ini_section(section_name, line) -{ - insert_lines: - # If the section is not there, we need to insert it - "[${section_name}]" - comment => "Insert section if it doesn't exist"; - - "${line}" - select_region => INI_section("${section_name}"), - comment => "Insert line in section ${section_name}"; -} - -# Ensure that a line is present in an xml tag -# Won't create the tag if not there (we don't know where to put it) -bundle edit_line ensure_line_in_xml_tag(tag_name, line) -{ - vars: - "section_start" string => "\s*<${tag_name}>\s*"; - "section_end" string => "\s*\s*"; - - insert_lines: - "${line}" - select_region => ncf_section_selector("${section_start}", "${section_end}"), - comment => "Insert line in section ${tag_name}"; -} - -bundle edit_line prepend(lines) -{ - insert_lines: - - "${lines}" - comment => "Prepending line: ${lines}", - location => start; -} - -bundle edit_line replace_line(regex, replacement) -{ - replace_patterns: - - "${regex}" - replace_with => value("${replacement}"), - comment => "Replace every occurrence of ${regex} with ${replacement}"; -} - -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}"; -} - -# DEPRECATED - for compatibility -body delete_select rudder_delete_if_not_in_list(lines_to_delete) -{ - delete_if_not_match_from_list => { @{lines_to_delete} }; -} - -# Select lines for deletion -# Select the lines that are not in the list (complete line match) -body delete_select ncf_delete_if_not_in_list(lines_to_delete) -{ - delete_if_not_match_from_list => { @{lines_to_delete} }; -} - -body select_region ncf_section_selector(section_start, section_end) -{ - select_start => "${section_start}"; - select_end => "${section_end}"; -} - -# DEPRECATED - for compatibility -body select_region rudder_section_selector(section_start, section_end) -{ - select_start => "${section_start}"; - select_end => "${section_end}"; -} - -# Edit AIX password file /etc/security/passwd -bundle edit_line ncf_ensure_AIX_password(username, password) { - vars: - "current_date" int => now(); - - classes: - # does the section exists, or should it be created ? - "section_absent" not => regline("${username}:", "${edit.filename}"); - - field_edits: - !section_absent:: - "\s*password\s*=.*" - # We need to put a space before password to keep the format password = - edit_field => col("=", "2", " ${password}", "set"), - select_region => ncf_section_AIX_user("${username}"); - - insert_lines: - section_absent:: - "${username}: - password = ${password} - lastupdate = ${current_date}" - insert_type => "preserve_block"; - -} - -# Define the lastupdate date when a password is changed -bundle edit_line ncf_edit_lastupdate_AIX_password(username) { - vars: - "current_date" int => now(); - - field_edits: - section_absent:: - "\s*lastupdate\s*=.*" - # We need to put a space before password to keep the format password = - edit_field => col("=", "2", " ${password}", "set"), - select_region => ncf_section_AIX_user("${username}"); - -} -# Select region in /etc/security/passwd file -body select_region ncf_section_AIX_user(username) -{ - select_start => "${username}:"; - select_end => ".*:"; -} - -bundle edit_line rudder_change_aix_password_entry(user, entry, content) -{ - field_edits: - - "\s*${entry}\s*=.*" - select_region => rudder_aix_user_section("${user}"), - edit_field => col("=","2"," ${content}","set"); - -} - -body select_region rudder_aix_user_section(x) -{ - select_start => "${x}:\s*"; - select_end => "\S*:\s*"; -} - -bundle edit_line insert_rudder_disclaimer -{ - vars: - "file_edit_header" string => "${rudder_parameters.rudder_file_edit_header}"; - - defaults: - "file_edit_header" string => "############################################################# -### 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. ### -############################################################# -", - if_match_regex => "${const.dollar}{rudder_parameters.rudder_file_edit_header}"; - - insert_lines: - - "${file_edit_header}" - location => start; -} - -# -# Select files older than X months -# -body file_select ncf_months_old(months) -{ - mtime => irange(0,ago(0,"${months}",0,0,0,0)); - file_result => "mtime"; -} - -# -# Select files older than X hours -# -body file_select ncf_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 ncf_minutes_old(minutes) -{ - mtime => irange(0,ago(0,0,0,0,"${minutes}",0)); - file_result => "mtime"; -} - -# DEPRECATED - for compatibility -body file_select rudder_common_minutes_old(minutes) -{ - mtime => irange(0,ago(0,0,0,0,"${minutes}",0)); - file_result => "mtime"; -} - -######################################################################## -# 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"; -} - -# Modular local copy_from body -body copy_from ncf_local_cp_method(from, method) -{ - source => "${from}"; - compare => "${method}"; - copy_backup => "timestamp"; -} - -# Modular remote copy_from body -# This body gets the CFEngine port from ncf's configuration. -body copy_from ncf_remote_cp_method(from, server, method) -{ - servers => { "${server}" }; - source => "${from}"; - portnumber => "${configuration.cfengine_port}"; - compare => "${method}"; - encrypt => "true"; - copy_backup => "timestamp"; -} - -# DEPRECATED -#server may be a list -body copy_from cp(from,server) -{ - servers => { "${server}" }; - source => "${from}"; - compare => "digest"; - community_edition:: - portnumber => "${system_common.community_port}"; -} - -# DEPRECATED -# 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"; - servers => { "${server}" }; - - community_edition:: - portnumber => "${system_common.community_port}"; -} - -body copy_from copy(from) -{ - source => "${from}"; - copy_backup => "false"; - preserve => "true"; -} - -# DEPRECATED -body copy_from copy_digest(from) -{ - source => "${from}"; - copy_backup => "timestamp"; - preserve => "true"; - compare => "digest"; - -} - -body copy_from digest_cp(from) -{ - source => "${from}"; - copy_backup => "timestamp"; - compare => "digest"; - copylink_patterns => { ".*" }; -} - - -# Define x prefixes/suffixed with promises outcome, based on return codes -# !DEPRECATED! -body classes classes_generic_return_codes(x, kept_return_code, repaired_return_code, failed_return_code) -{ - kept_returncodes => { "${kept_return_code}" }; - repaired_returncodes => { "${repaired_return_code}" }; - failed_returncodes => { "${failed_return_code}" }; - - 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", "${x}_error" }; - repair_denied => { "repair_denied_$(x)", "$(x)_denied", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error" }; - repair_timeout => { "repair_timeout_$(x)", "$(x)_timeout", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error" }; - promise_kept => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached" }; -} - -# Define x prefixes/suffixed with promises outcome, based on return codes -body classes classes_generic_return_single_code_two(x, y, kept_return_code, repaired_return_code, failed_return_code) -{ - kept_returncodes => { "${kept_return_code}" }; - repaired_returncodes => { "${repaired_return_code}" }; - failed_returncodes => { "${failed_return_code}" }; - - promise_repaired => { "promise_repaired_$(x)", "$(x)_repaired", "$(x)_ok", "$(x)_reached", - "promise_repaired_$(y)", "$(y)_repaired", "$(y)_ok", "$(y)_reached" }; - repair_failed => { "repair_failed_$(x)", "$(x)_failed", "$(x)_not_ok", "$(x)_error", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", - "repair_failed_$(y)", "$(y)_failed", "$(y)_not_ok", "$(y)_error", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached" }; - repair_denied => { "repair_denied_$(x)", "$(x)_denied", "$(x)_not_ok", "$(x)_error", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", - "repair_denied_$(y)", "$(y)_denied", "$(y)_not_ok", "$(y)_error", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached" }; - repair_timeout => { "repair_timeout_$(x)", "$(x)_timeout", "$(x)_not_ok", "$(x)_error", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", - "repair_timeout_$(y)", "$(y)_timeout", "$(y)_not_ok", "$(y)_error", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached" }; - promise_kept => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached", - "promise_kept_$(y)", "$(y)_kept", "$(y)_ok", "$(y)_not_repaired", "$(y)_reached" }; -} - -# Define x prefixes/suffixed with promises outcome, based on return codes -body classes classes_generic_return_code_list_two(x, y, kept_return_codes, repaired_return_codes) -{ - kept_returncodes => { @{kept_return_codes} }; - repaired_returncodes => { @{repaired_return_codes} }; - - promise_repaired => { "promise_repaired_$(x)", "$(x)_repaired", "$(x)_ok", "$(x)_reached", - "promise_repaired_$(y)", "$(y)_repaired", "$(y)_ok", "$(y)_reached" }; - repair_failed => { "repair_failed_$(x)", "$(x)_failed", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error", - "repair_failed_$(y)", "$(y)_failed", "$(y)_not_ok", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached", "${y}_error" }; - repair_denied => { "repair_denied_$(x)", "$(x)_denied", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error", - "repair_denied_$(y)", "$(y)_denied", "$(y)_not_ok", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached", "${y}_error"}; - repair_timeout => { "repair_timeout_$(x)", "$(x)_timeout", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error", - "repair_timeout_$(y)", "$(y)_timeout", "$(y)_not_ok", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached", "${y}_error" }; - promise_kept => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached", - "promise_kept_$(y)", "$(y)_kept", "$(y)_ok", "$(y)_not_repaired", "$(y)_reached" }; -} - -# Define x prefixes/suffixed with true/false outcome, based on return codes -# Note that an unknown return code is an error and doesn't return false nor true, just an error. -body classes classes_generic_return_boolean_list_two(x, y, boolean_prefix, true_return_codes, false_return_codes) -{ - kept_returncodes => { @{true_return_codes} }; - repaired_returncodes => { @{false_return_codes} }; - - promise_repaired => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached", - "promise_kept_$(y)", "$(y)_kept", "$(y)_ok", "$(y)_not_repaired", "$(y)_reached", "${boolean_prefix}_false" }; - repair_failed => { "repair_failed_$(x)", "$(x)_failed", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error", - "repair_failed_$(y)", "$(y)_failed", "$(y)_not_ok", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached", "${y}_error" }; - repair_denied => { "repair_denied_$(x)", "$(x)_denied", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error", - "repair_denied_$(y)", "$(y)_denied", "$(y)_not_ok", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached", "${y}_error" }; - repair_timeout => { "repair_timeout_$(x)", "$(x)_timeout", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", "${x}_error", - "repair_timeout_$(y)", "$(y)_timeout", "$(y)_not_ok", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached", "${y}_error" }; - promise_kept => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached", - "promise_kept_$(y)", "$(y)_kept", "$(y)_ok", "$(y)_not_repaired", "$(y)_reached", "${boolean_prefix}_true" }; -} - -# Define x and y prefixed/suffixed with promise outcome -body classes classes_generic_two(x,y) -{ - promise_repaired => { "promise_repaired_$(x)", "$(x)_repaired", "$(x)_ok", "$(x)_reached", - "promise_repaired_$(y)", "$(y)_repaired", "$(y)_ok", "$(y)_reached" }; - repair_failed => { "repair_failed_$(x)", "$(x)_failed", "$(x)_not_ok", "$(x)_error", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", - "repair_failed_$(y)", "$(y)_failed", "$(y)_not_ok", "$(y)_error", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached" }; - repair_denied => { "repair_denied_$(x)", "$(x)_denied", "$(x)_not_ok", "$(x)_error", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", - "repair_denied_$(y)", "$(y)_denied", "$(y)_not_ok", "$(y)_error", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached" }; - repair_timeout => { "repair_timeout_$(x)", "$(x)_timeout", "$(x)_not_ok", "$(x)_error", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached", - "repair_timeout_$(y)", "$(y)_timeout", "$(y)_not_ok", "$(y)_error", "$(y)_not_kept", "$(y)_not_repaired", "$(y)_reached" }; - promise_kept => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached", - "promise_kept_$(y)", "$(y)_kept", "$(y)_ok", "$(y)_not_repaired", "$(y)_reached" }; -} - -body classes common_classes_exclusive_persist_codes(prefix, persist, keptcodes, repairedcodes, errorcodes) -{ - - kept_returncodes => { "@{keptcodes}" }; - repaired_returncodes => { "@{repairedcodes}" }; - failed_returncodes => { "@{errorcodes}" }; - - promise_kept => { "${prefix}_kept" , "${prefix}_ok" }; - cancel_kept => { "${prefix}_repaired", "${prefix}_failed", "${prefix}_error" }; - - promise_repaired => { "${prefix}_repaired", "${prefix}_ok" }; - cancel_repaired => { "${prefix}_kept", "${prefix}_failed", "${prefix}_error" }; - - repair_failed => { "${prefix}_failed" , "${prefix}_error" }; - repair_denied => { "${prefix}_denied" , "${prefix}_error" }; - repair_timeout => { "${prefix}_timeout" , "${prefix}_error" }; - cancel_notkept => { "${prefix}_kept", "${prefix}_ok", "${repaired}" }; - - persist_time => "${persist}"; - -} - -########################################################################################### -# 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 persistent_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 -################################################ -# DEPRECATED -body classes kept_if_else(kept, yes,no) - -{ - promise_kept => { "${kept}" }; - promise_repaired => { "${yes}" }; - repair_failed => { "${no}" }; - repair_denied => { "${no}" }; - repair_timeout => { "${no}" }; -} - -# DEPRECATED -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}" }; -} - -########################################################################################### -# 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}" }; -} - -# WARNING !!! -# For new class prefix migration only, this will be removed when migration is over -body process_count any_count_two(cl, cl2) -{ - match_range => "0,0"; - out_of_range_define => { "$(cl)", "$(cl2)" }; -} - -####################################################### -# Match all variants of cron processes -# DEPRECATED -body process_select cron_bin -{ - command => "(/usr/sbin/)?crond?( -n| -f| -l notice)*"; - process_result => "command"; -} - -# Enforce or not content of a file -######################################################################## -# Same as std_defs, allowing user to specify the file erase policy # -######################################################################## -body edit_defaults ncf_empty_select(select) -{ - empty_file_before_editing => "${select}"; - max_file_size => "25M"; - edit_backup => "timestamp"; -} - -# DEPRECATED -body edit_defaults rudder_empty_select(select) -{ - inherit_from => ncf_empty_select("${select}"); -} - -body edit_defaults empty_size(size) -{ - empty_file_before_editing => "true"; - edit_backup => "false"; - max_file_size => "${size}"; -} - -# DEPRECATED -body edit_defaults noempty_backup -{ - inherit_from => ncf_empty_select("false"); -} - -# DEPRECATED -body edit_defaults empty_backup -{ - inherit_from => ncf_empty_select("true"); -} - -# Combines classes from two specified prefixes -# The worst outcome is kept (logical AND) -bundle agent ncf_classes_combine_two(first_prefix, second_prefix, destination_prefix) -{ - classes: - "first_reached" expression => "${first_prefix}_reached"; - "second_reached" expression => "${second_prefix}_reached"; - - destination_exists.first_reached.second_reached:: - "${destination_prefix}_ok" expression => "${first_prefix}_ok.${second_prefix}_ok", - scope => "namespace"; - - "${destination_prefix}_kept" expression => "${first_prefix}_kept.${second_prefix}_kept", - scope => "namespace"; - - "promise_kept_${destination_prefix}" expression => "${destination_prefix}_kept", - scope => "namespace"; - - "${destination_prefix}_repaired" expression => "(${first_prefix}_ok.${second_prefix}_repaired)|(${first_prefix}_repaired.${second_prefix}_ok)", - scope => "namespace"; - - "promise_repaired_${destination_prefix}" expression => "${destination_prefix}_repaired", - scope => "namespace"; - - "${destination_prefix}_reached" expression => "${first_prefix}_reached|${second_prefix}_reached", - scope => "namespace"; - - "${destination_prefix}_failed" expression => "${first_prefix}_failed|${second_prefix}_failed", - scope => "namespace"; - - "repair_failed_${destination_prefix}" expression => "${destination_prefix}_failed", - scope => "namespace"; - - "${destination_prefix}_denied" expression => "${first_prefix}_denied|${second_prefix}_denied", - scope => "namespace"; - - "repair_denied_${destination_prefix}" expression => "${destination_prefix}_denied", - scope => "namespace"; - - "${destination_prefix}_timeout" expression => "${first_prefix}_timeout|${second_prefix}_timeout", - scope => "namespace"; - - "repair_timeout_${destination_prefix}" expression => "${destination_prefix}_timeout", - scope => "namespace"; - - "${destination_prefix}_error" expression => "${first_prefix}_error|${second_prefix}_error", - scope => "namespace"; - - "${destination_prefix}_not_ok" expression => "!${destination_prefix}_ok", - scope => "namespace"; - - "${destination_prefix}_not_kept" expression => "!${destination_prefix}_kept", - scope => "namespace"; - - "${destination_prefix}_not_repaired" expression => "!${destination_prefix}_repaired", - scope => "namespace"; - - classes: - # this line will not be evaluated by cfengine if destination_prefix contains a variable that does not exist - # and it will always be evaluated to true otherwise - "destination_defined" expression => strcmp("${destination_prefix}", "${destination_prefix}"); - "destination_not_empty" not => strcmp("${destination_prefix}", ""); - "destination_exists" and => { "destination_defined", "destination_not_empty" }; - - methods: - first_reached.!second_reached:: - "copy first" usebundle => _classes_copy("${first_prefix}", "${destination_prefix}"); - - !first_reached.second_reached:: - "copy second" usebundle => _classes_copy("${second_prefix}", "${destination_prefix}"); -} - -# Copies classes with source_prefix into destination_prefix -# This copies the whole class set -bundle agent ncf_classes_copy(source_prefix, destination_prefix) -{ - vars: - "prefix" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout" }; - "suffix" slist => { "repaired", "ok", "reached", "failed", "not_ok", "not_kept", "not_repaired", "denied", "timeout", "kept", "error" }; - - destination_exists:: - # Copy result classes prefixes - "${prefix}_local_destination_prefix" - string => "${prefix}_${destination_prefix}", - ifvarclass => "${prefix}_${source_prefix}", - classes => always("${prefix}_${destination_prefix}"); - - # Copy result classes suffixes - "local_destination_prefix_${suffix}" - string => "${destination_prefix}_${suffix}", - ifvarclass => "${source_prefix}_${suffix}", - classes => always("${destination_prefix}_${suffix}"); - - classes: - # this line will not be evaluated by cfengine if destination_prefix contains a variable that does not exist - # and it will always be evaluated to true otherwise - "destination_defined" expression => strcmp("${destination_prefix}", "${destination_prefix}"); - "destination_not_empty" not => strcmp("${destination_prefix}", ""); - "destination_exists" and => { "destination_defined", "destination_not_empty" }; - -} - -######################################################################## -# 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}"; -} - -# defines ncf_services_${service}_${action} -# -# Standard actions are: -# -# * start -# * stop -# * restart -# * reload (with an alias to refresh) -# * is-active (with an alias to status) -# * is-active-process (in this case, the "service" parameter is the regex to match againt process list) -# * enable -# * disable -# * is-enabled -# -# When using service, init.d or systemd, any unkown action will be passed as is to the command -# wich allows support for try-restart, force-reload, etc. -# -# This bundle can be seen as a kind of service_bundle, but: -# -# * No concept of state, every call is an action that will be executed. State must be implemented at higher level. -# * More supported actions, services promises are limited to start/stop/enable/disable -# * Special actions (is-*) for checks -# -bundle agent ncf_services(service, action) -{ - vars: - - ########################################################################### - # All actions - ########################################################################### - - # These commands (sadly) are not completely static (as on debian 8 and upstart the outcome depends on the service) - - # systemd - pass1.!is_init_service.systemctl_utility_present:: - "action_command" string => "${paths.path[systemctl]} --no-ask-password ${action} ${service}.service"; - "method" string => "systemctl"; - - # upstart - pass1.!systemctl_utility_present.is_upstart_service:: - # non-boot - "upstart_action_cmd[start]" string => "/sbin/initctl start ${service}"; - "upstart_action_cmd[stop]" string => "/sbin/initctl stop ${service}"; - "upstart_action_cmd[restart]" string => "/sbin/initctl restart ${service}"; - "upstart_action_cmd[reload]" string => "/sbin/initctl reload ${service}"; - "upstart_action_cmd[is-active]" string => "/sbin/initctl status ${service} 2>&1 | grep -q ' start/'"; - # boot - "upstart_action_cmd[enable]" string => "${paths.path[sed]} -i '/^manual/d' /etc/init/${service}.override"; - "upstart_action_cmd[disable]" string => "${paths.path[echo]} manual >> /etc/init/${service}.override"; - # this one may not be true is it was disabled by another way - "upstart_action_cmd[is-enabled]" string => "${paths.path[grep]} -q '^manual' /etc/init/${service}.override; test $? -ne 0"; - "action_command" string => "${upstart_action_cmd[${action}]}"; - "method" string => "upstart"; - - # svcadm/svcs - pass1.!systemctl_utility_present.!is_upstart_service.svcadm_utility_present:: - # non-boot - "svc_action_cmd[start]" string => "${paths.path[svcadm]} enable -s -t ${service}"; - "svc_action_cmd[stop]" string => "${paths.path[svcadm]} disable -s -t ${service}"; - "svc_action_cmd[restart]" string => "${paths.path[svcadm]} restart -s ${service}"; - "svc_action_cmd[reload]" string => "${paths.path[svcadm]} refresh -s ${service}"; - "svc_action_cmd[is-active]" string => "${paths.path[svcs]} -H ${service} | ${paths.path[grep]} '^online'"; - # boot - "svc_action_cmd[enable]" string => "${paths.path[svcadm]} enable -s ${service}"; - "svc_action_cmd[disable]" string => "${paths.path[svcadm]} disable -s ${service}"; - "svc_action_cmd[is-enabled]" string => "${paths.path[svcs]} -l ${service} | ${paths.path[egrep]} '^enabled [ ]+(true|false \(temporary\))'"; - "action_command" string => "${svc_action_cmd[${action}]}"; - "method" string => "svcadm/svcs"; - - # Slackware - pass1.slackware:: - "method" string => "/etc/rc.d"; - - ########################################################################### - # Boot actions - ########################################################################### - - # chkconfig - pass1.is_boot_action.(!systemctl_utility_present|is_init_service).!is_upstart_service.!svcadm_utility_present.chkconfig_utility_present:: - "chkconfig_action_cmd[enable]" string => "${paths.path[chkconfig]} ${service} on"; - "chkconfig_action_cmd[disable]" string => "${paths.path[chkconfig]} ${service} off"; - "chkconfig_action_cmd[is-enabled]" string => "${paths.path[chkconfig]} --list ${service} 2>&1 | ${paths.path[grep]} -q -e 3:on -e B:on"; - "action_command" string => "${chkconfig_action_cmd[${action}]}"; - "method" string => "chkconfig"; - - # update-rc.d - # WARN: "is-enabled" will use /etc/rcX.d/ directly - pass1.is_boot_action.!is_check_action.(!systemctl_utility_present|is_init_service).!is_upstart_service.!svcadm_utility_present.!chkconfig_utility_present.update_rcd_utility_present:: - "action_command" string => "${paths.path[update_rc_d]} ${service} ${action}"; - "method" string => "update-rc.d"; - - # chitab/lsitab - pass1.is_boot_action.!systemctl_utility_present.!is_upstart_service.!svcadm_utility_present.!chkconfig_utility_present.!update_rcd_utility_present.chitab_utility_present:: - "chitab_action_cmd[enable]" string => "/usr/sbin/chitab \"`lsitab -a | grep '^${service}:' | sed 's/\([^:]*\):\([^:]*\):[^:]*:\(.*\)/\1:\2:respawn:\3/'`\""; - "chitab_action_cmd[disable]" string => "/usr/sbin/chitab \"`lsitab -a | grep '^${service}:' | sed 's/\([^:]*\):\([^:]*\):[^:]*:\(.*\)/\1:\2:off:\3/'`\""; - "lsitab_action_cmd[is-enabled]" string => "/usr/sbin/lsitab -a | ${paths.path[egrep]} '^${service}:[0-9]+:(respawn|boot|bootwait|wait|once|initdefault|sysinit):'"; - "action_command" string => "${lsitab_action_cmd[${action}]}"; - "method" string => "lsitab/chitab"; - - # /etc/rcX.d/ - pass1.is_boot_action.is_check_action.(!systemctl_utility_present|is_init_service).!is_upstart_service.!svcadm_utility_present.!chkconfig_utility_present.!chitab_utility_present.!slackware:: - "action_command" string => "${paths.path[test]} -f /etc/rc`/sbin/runlevel | ${paths.path[cut]} -d' ' -f2`.d/S??${service}"; - "method" string => "/etc/rcX.d/"; - - # Slackware boot actions are not performed by command, they are implemented in the 'methods' promises - - ########################################################################### - # Non-boot actions - ########################################################################### - - # service - # WARN: Some actions may not be supported by the init script - pass1.!is_boot_action.(!systemctl_utility_present|is_init_service).!is_upstart_service.!svcadm_utility_present.service_utility_present:: - "action_command" string => "${paths.path[service]} ${service} ${action}", - ifvarclass => "!is_check_action"; - # is-active is mapped to "status" - "action_command" string => "${paths.path[service]} ${service} status", - ifvarclass => "is_check_action"; - "method" string => "service"; - - # src - pass1.!is_boot_action.!systemctl_utility_present.!is_upstart_service.!svcadm_utility_present.!service_utility_present.startsrc_utility_present:: - "svc_action_cmd[start]" string => "/usr/bin/startsrc -s ${service}"; - "svc_action_cmd[stop]" string => "/usr/bin/stopsrc -s ${service}"; - "svc_action_cmd[restart]" string => "/usr/bin/stopsrc -s ${service} && until /usr/bin/lssrc -s ${service} | ${paths.grep} -q inoperative; do ${paths.perl} -e 'select(undef,undef,undef,.25)'; done; /usr/bin/startsrc -s ${service_name}"; - "svc_action_cmd[reload]" string => "/usr/bin/refresh -s ${service}"; - "svc_action_cmd[is-active]" string => "/usr/bin/lssrc -s ${service} | ${paths.path[grep]} -q 'active'"; - "action_command" string => "${svc_action_cmd[${action}]}"; - "method" string => "src"; - - # init.d - # WARN: Some actions may not be supported by the init script - pass1.!is_boot_action.(!systemctl_utility_present|is_init_service).!is_upstart_service.!svcadm_utility_present.!service_utility_present.!startsrc_utility_present.is_init_service:: - "action_command" string => "/etc/init.d/${service} ${action}", - ifvarclass => "!is_check_action"; - # is-active is mapped to "status" - "action_command" string => "/etc/init.d/${service} status", - ifvarclass => "is_check_action"; - "method" string => "/etc/init.d/"; - - # Slackware - pass1.slackware.!is_boot_action:: - "action_command" string => "/etc/rc.d/rc.${service} ${action}", - ifvarclass => "!is_check_action"; - # is-active is mapped to "status" - "action_command" string => "/etc/rc.d/rc.${service} status", - ifvarclass => "is_check_action"; - - # windows - # Implementation is done in services promises - windows:: - "method" string => "Windows Service Manager"; - - ########################################################################### - - any:: - "canonified_service" string => canonify("${service}"); - "canonified_action" string => canonify("${action}"); - "canonified_action_command" string => canonify("${action_command}"); - - "class_prefix" string => "ncf_services_${canonified_service}_${canonified_action}"; - - defaults: - # status is an alias to is-active (in systemd, it is not the same thing the only difference is the output, which is not kept anyway) - "actual_action" string => "is-active", if_match_regex => "status"; - - # refresh is an alias to reload - "actual_action" string => "reload", if_match_regex => "refresh"; - - classes: - - windows:: - "is_valid_action" or => { - strcmp("start", "${action}"), - strcmp("stop", "${action}"), - strcmp("restart", "${action}"), - }; - "is_restart_action" expression => strcmp("restart", "${action}"); - - any:: - "is_process_action" expression => strcmp("is-active-process", "${action}"); - - "is_boot_action" or => { - strcmp("enable", "${action}"), - strcmp("disable", "${action}"), - strcmp("is-enabled", "${action}") - }; - - "is_check_action" or => { - strcmp("is-active", "${action}"), - strcmp("is-active-process", "${action}"), - strcmp("is-enabled", "${action}") - }; - - # Due to lack of integration between upstart and init scripts, we have to make different cases. - "is_upstart_service" not => returnszero("/sbin/initctl status ${service} 2>&1 | ${paths.path[grep]} -E 'Unknown job|Unable to connect to Upstart' > /dev/null", "useshell"), - ifvarclass => "ubuntu.initctl_utility_present"; - - # Due to compatibility issues when mixing init.d/service and systemctl calls, we use the init script when present - "is_init_service" expression => fileexists("/etc/init.d/${service}"); - - pass1:: - "method_found" expression => isvariable("method"); - - ##### - # Actual command - for checks on non-windows systems - ##### - pass1.is_check_action.!windows.!is_process_action.method_found.!(slackware.is_boot_action):: - "action_ok" expression => returnszero("${action_command} 2>&1 > /dev/null", "useshell"); - - any:: - "pass3" expression => "pass2"; - "pass2" expression => "pass1"; - "pass1" expression => "any"; - - methods: - - ##### - # Actual command - for actions on non-windows systems, non using systemd, non-slackware - ##### - pass2.is_check_action.!windows.!is_process_action.method_found.action_ok.!slackware:: - "force_success_class" usebundle => _classes_success("${class_prefix}"); - - pass2.is_check_action.!windows.!is_process_action.method_found.!action_ok.!slackware:: - "force_failure_class" usebundle => _classes_failure("${class_prefix}"); - - # Method not found - pass2.(!method_found|(windows.!is_valid_action)):: - "force_failure_class" usebundle => _classes_failure("${class_prefix}"); - - # Classes for process check - pass2:: - "force_failure_process" usebundle => _classes_failure("${class_prefix}"), - ifvarclass => "${class_prefix}_checked_not_ok"; - - "force_success_process" usebundle => _classes_success("${class_prefix}"), - ifvarclass => "${class_prefix}_checked_ok"; - # Slackware boot actions - pass2.slackware.is_boot_action:: - "action" usebundle => slackware_boot_services("${service}", "${action}", "${class_prefix}"); - processes: - - ########################################################################### - # is-active-process action - ########################################################################### - - is_process_action:: - "${service}" - process_count => any_count("${class_prefix}_checked_ok"); - - "${service}" - restart_class => "${class_prefix}_checked_not_ok"; - - services: - - ########################################################################### - # Windows - only non-boot actions - ########################################################################### - - ##### - # Actual command - for actions on windows systems - ##### - # Restart causes the agent to fail, so we must replace it by stop and start - windows.is_valid_action.!is_restart_action:: - "${service}" - service_policy => "${action}", - classes => classes_generic("${class_prefix}"); - - windows.is_restart_action:: - "${service}" - service_policy => "stop", - classes => classes_generic("${class_prefix}_stop_service"); - - "${service}" - service_policy => "start", - classes => classes_generic("${class_prefix}"), - ifvarclass => "${class_prefix}_stop_service_ok"; - - commands: - ##### - # Actual command - for actions on non-windows systems - ##### - # We need to use our own commands: implementation here rather than calling command_execution - # because of a CFEngine bug (https://dev.cfengine.com/issues/5840) that causes systemctl - # to fail if it can't find /dev/tty, which is the case unless using no_output => true - # It also avoids reporting on command_execution for all platforms - pass2.!is_check_action.!windows.!is_process_action.method_found.!(slackware.is_boot_action):: - "${action_command}" - contain => in_shell_and_silent, - classes => classes_generic("${class_prefix}"); - - reports: - - pass3.error.!method_found:: - "${configuration.error} Could not find a supported service management method on this system"; - pass3.error.!is_valid_action:: - "${configuration.error} The ${action} action is not supported on Windows (use 'start', 'stop' or 'restart')"; - - pass3.info.method_found.(!windows|is_valid_action):: - "${configuration.info} Executing ${action} on ${service} using the ${method} method"; - - pass3.debug.method_found.!windows:: - "${configuration.debug} Executing: '${action_command}'"; -} - -# Add parameter in key->values line, where -> is key_value_separator -bundle edit_line ncf_add_parameter_in_list(key, key_value_separator, parameter_separator, parameter) { - vars: - "escaped_key" string => escape("${key}"); - - - replace_patterns: - "^(${escaped_key}\s*${key_value_separator}\s*)(.*)$" - replace_with => ncf_add_parameter_with_separator("${parameter}", "${parameter_separator}"); -} - -# Add parameter in key->[values] line, where -> is key_value_separator and [ ] are leading and closing char separator -bundle edit_line ncf_add_parameter_in_list_with_enclosing_chars(key, key_value_separator, parameter_separator, parameter, leading_char_separator, closing_char_separator) { - vars: - "escaped_key" string => escape("${key}"); - "escaped_leading_char" string => escape("${leading_char_separator}"); - "escaped_closing_char" string => escape("${closing_char_separator}"); - - replace_patterns: - "^(${escaped_key}\s*${key_value_separator}\s*)(${escaped_leading_char})(.*)(${escaped_closing_char})\s*$" - replace_with => ncf_add_parameter_with_separator_and_enclosing_characters("${parameter}", "${parameter_separator}"); -} - -# Remove parameter_regex in key->[values] line, where -> is key_value_separator and [ ] are leading and closing char separator. Note: any whitespace between parameter_regex and parameter_separator will be also removed -bundle edit_line ncf_remove_parameter_in_list(key, key_value_separator, parameter_separator, parameter_regex, leading_char_separator, closing_char_separator) { - vars: - "escaped_key" string => escape("${key}"); - "escaped_leading_char" string => escape("${leading_char_separator}"); - "escaped_closing_char" string => escape("${closing_char_separator}"); - - replace_patterns: - "^(${escaped_key}\s*${key_value_separator}\s*${escaped_leading_char}.*)(${parameter_separator}+\s*${parameter_regex}|${parameter_regex}\s*${parameter_separator}+)(.*${escaped_closing_char})\s*$" - replace_with => value("${match.1}${match.3}"); -} - -body replace_with ncf_add_parameter_with_separator(parameter, parameter_separator) { - occurrences => "first"; - replace_value => "${match.1}${match.2}${parameter_separator}${parameter}"; -} - -body replace_with ncf_add_parameter_with_separator_and_enclosing_characters(parameter, parameter_separator) { - occurrences => "first"; - replace_value => "${match.1}${match.2}${match.3}${parameter_separator}${parameter}${match.4}"; -} - -# DEPRECATED -body perms u_p(p) -{ - inherit_from => m("${p}"); -} - -################################################ -# Simple group adjustment body -################################################ -body perms group(group) -{ - groups => { "${group}" }; -} - -######################################################################## -# Change group and mode of a file/directory # -######################################################################## -body perms mg(mode,group) -{ - groups => { "${group}" }; - mode => "${mode}"; -} - -bundle agent slackware_boot_services(service, action, class_prefix) -{ - vars: - "canon_service" string => canonify("${service}"); - - classes: - - "action_enable" expression => strcmp("enable", ${action}); - "action_disable" expression => strcmp("disable", ${action}); - "action_is_enabled" expression => strcmp("is-enabled", ${action}); - - methods: - - action_disable:: - "chmod 644" usebundle => perm_on_file("/etc/rc.d/rc.${service}", "644", "${class_prefix}"); - - action_enable:: - "chmod 755" usebundle => perm_on_file("/etc/rc.d/rc.${service}", "755", "${class_prefix}"); - "block in init scripts" usebundle => service_block_rc_d("${service}", "${class_prefix}"); - - action_is_enabled:: - "enable dry run" usebundle => push_dry_run_mode("true"); - "chmod 755" usebundle => perm_on_file("/etc/rc.d/rc.${service}", "755", "${canon_service}_init_script_execmod"); - "block in init scripts" usebundle => service_block_rc_d("${service}", "${class_prefix}"), - ifvarclass => "${canon_service}_init_script_execmod_ok"; - "ifnoexecmod, new" usebundle => _classes_copy("${canon_service}_init_script_execmod", "${class_prefix}"), - ifvarclass => "${canon_service}_init_script_execmod_not_ok"; - "disable dry run" usebundle => pop_dry_run_mode(); -} - -bundle agent perm_on_file(file, mod, class_prefix) -{ - vars: - "canonfile" string => canonify("${file}"); - - files: - "${file}" - perms => m("${mod}"), - classes => classes_generic("${class_prefix}"); -} - -bundle agent service_block_rc_d(service, new_class_prefix) -{ - vars: - "canon_service" string => canonify("${service}"); - - # When the dry run mode is enabled, the needed changes will not be applied, but the classes will be copied - files: - "/etc/rc.d/rc.local" - edit_line => edit_service_block_rc_d("${service}"), - classes => classes_generic("service_${canon_service}_block_in_rc_local"); - - "/etc/rc.d/rc.local_shutdown" - create => "true", - edit_line => edit_service_block_shutdown("${service}"), - classes => classes_generic("service_${canon_service}_block_in_rc_shutdown"); - - "/etc/rc.d/rc.M" - edit_line => edit_service_block_rc_d("${service}"), - classes => classes_generic("${class_prefix}"), - ifvarclass => "service_${canon_service}_block_in_rc_local_not_ok"; - - methods: - "combine" usebundle => ncf_classes_combine_two("service_${canon_service}_block_in_rc_local", "service_${canon_service}_block_in_rc_shutdown", "service_${canon_service}_block_in_rc_both"); - "new classes" usebundle => ncf_classes_copy("service_${service}_block_in_rc_both", "${class_prefix}"), - ifvarclass => "service_${canon_service}_block_in_rc_both_ok"; -} - -bundle edit_line edit_service_block_rc_d(service, action) -{ - insert_lines: -"if [ -x /etc/rc.d/rc.${service} ]; then - . /etc/rc.d/rc.${service} start -fi" - insert_type =>"preserve_block"; -} - -bundle edit_line edit_service_block_shutdown(service) -{ - insert_lines: -"if [ -x /etc/rc.d/rc.${service} ]; then - . /etc/rc.d/rc.${service} stop -fi" - insert_type =>"preserve_block"; -} diff --git a/tree/20_cfe_basics/old_packages.cf b/tree/20_cfe_basics/old_packages.cf new file mode 100644 index 000000000..c303ef8c6 --- /dev/null +++ b/tree/20_cfe_basics/old_packages.cf @@ -0,0 +1,537 @@ +##################################################################################### +# Copyright 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 . +# +##################################################################################### + +# DEPRECATED +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}'"; +} + +# DEPRECATED +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}'"; + +} + +# DEPRECATED +body package_method yum_rpm_no_version +{ + package_changes => "bulk"; + package_list_command => "/bin/rpm -qa --qf '%{name}.%{arch} %{version}-%{release}\n'"; + package_patch_list_command => "/usr/bin/yum ${redhat_knowledge.yum_options} check-update"; + + package_list_name_regex => "([^.]+).*"; + package_list_version_regex => "[^\s]\s+([^\s]+).*"; + package_list_arch_regex => "[^.]+\.([^\s]+).*"; + + package_installed_regex => ".*"; + package_name_convention => "$(name)"; + + # just give the package name to rpm to delete, otherwise it gets "name.*" (from package_name_convention above) + package_delete_convention => "$(name)"; + + # set it to "0" to avoid caching of list during upgrade + package_list_update_command => "/usr/bin/yum ${redhat_knowledge.yum_options} check-update"; + 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 => "$(redhat_knowledge.call_yum) $(redhat_knowledge.yum_options) -y install"; + package_update_command => "$(redhat_knowledge.call_yum) $(redhat_knowledge.yum_options) -y update"; + package_patch_command => "$(redhat_knowledge.call_yum) $(redhat_knowledge.yum_options) -y update"; + package_delete_command => "$(rpm_knowledge.call_rpm) -e --nodeps"; + package_verify_command => "$(rpm_knowledge.call_rpm) -V"; + package_noverify_returncode => "1"; + package_version_less_command => "$(redhat_knowledge.rpm_compare_less)"; + package_version_equal_command => "$(redhat_knowledge.rpm_compare_equal)"; +} + +# Install packages using yum localinstall, disable package caching +# DEPRECATED +body package_method redhat_local_install +{ + redhat:: + package_changes => "bulk"; + package_list_command => "/bin/rpm -qa --qf '%{name} %{version}-%{release} %{arch}\n'"; + package_patch_list_command => "/usr/bin/yum ${redhat_knowledge.yum_options} 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_command => "/usr/bin/yum ${redhat_knowledge.yum_options} check-update"; + 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 ${redhat_knowledge.yum_options} -y localinstall"; + package_update_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; + package_patch_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; + package_delete_command => "/bin/rpm -e --nodeps --allmatches"; + package_verify_command => "/bin/rpm -V"; + package_noverify_returncode => "1"; + package_version_less_command => "$(redhat_knowledge.rpm_compare_less)"; + package_version_equal_command => "$(redhat_knowledge.rpm_compare_equal)"; +} +# Install packages using yum standard install, disable package caching +# DEPRECATED +body package_method redhat_install +{ + redhat:: + package_changes => "bulk"; + package_list_command => "/bin/rpm -qa --qf '%{name} %{version}-%{release} %{arch}\n'"; + package_patch_list_command => "/usr/bin/yum ${redhat_knowledge.yum_options} 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_command => "/usr/bin/yum ${redhat_knowledge.yum_options} check-update"; + 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 ${redhat_knowledge.yum_options} -y install"; + package_update_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; + package_patch_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; + package_delete_command => "/bin/rpm -e --nodeps --allmatches"; + package_verify_command => "/bin/rpm -V"; + package_noverify_returncode => "1"; + package_version_less_command => "$(redhat_knowledge.rpm_compare_less)"; + package_version_equal_command => "$(redhat_knowledge.rpm_compare_equal)"; +} + +# DEPRECATED +body package_method debian_local_install +{ + package_changes => "individual"; + package_list_command => "$(debian_knowledge.call_dpkg) -l"; + # set it to "0" to avoid caching of list during upgrade + package_list_update_command => "$(debian_knowledge.call_apt_get) update"; + package_list_update_ifelapsed => "0"; + 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)" }; + package_add_command => "$(debian_knowledge.call_dpkg) --install"; + package_delete_command => "$(debian_knowledge.call_dpkg) --purge"; + package_update_command => "$(debian_knowledge.call_dpkg) --install"; + package_patch_command => "$(debian_knowledge.call_dpkg) --install"; + + # make correct version comparisons + package_version_less_command => "$(debian_knowledge.dpkg_compare_less)"; + package_version_equal_command => "$(debian_knowledge.dpkg_compare_equal)"; + + x86_64:: + package_name_convention => "$(name)_$(version)_amd64.deb"; + i686:: + package_name_convention => "$(name)_$(version)_i386.deb"; + have_aptitude:: + package_patch_list_command => "/usr/bin/aptitude --assume-yes --simulate --verbose full-upgrade"; + package_patch_name_regex => "^Inst\s+(\S+)\s+.*"; + package_patch_version_regex => "^Inst\s+\S+\s+\[?\(?([^\],\s]+).*"; + !have_aptitude:: + package_patch_list_command => "$(debian_knowledge.call_apt_get) --just-print dist-upgrade"; + package_patch_name_regex => "^Inst\s+(\S+)\s+.*"; + package_patch_version_regex => "^Inst\s+\S+\s+\[?\(?([^\],\s]+).*"; +} + +# DEPRECATED +body package_method ncf_generic +{ + SuSE:: + 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_command => "/usr/bin/zypper --non-interactive refresh"; + package_list_update_ifelapsed => "240"; # 4 hours + package_installed_regex => "i.*"; + package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*"; + package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; + package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; + 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 ${redhat_knowledge.yum_options} 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_command => "/usr/bin/yum ${redhat_knowledge.yum_options} check-update"; + 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 ${redhat_knowledge.yum_options} -y install"; + package_update_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; + package_patch_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; + package_delete_command => "/bin/rpm -e --nodeps --allmatches"; + package_verify_command => "/bin/rpm -V"; + package_version_less_command => "$(redhat_knowledge.rpm_compare_less)"; + package_version_equal_command => "$(redhat_knowledge.rpm_compare_equal)"; + + debian:: + package_changes => "bulk"; + package_list_command => "$(debian_knowledge.call_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 + + # make correct version comparisons + package_version_less_command => "$(debian_knowledge.dpkg_compare_less)"; + package_version_equal_command => "$(debian_knowledge.dpkg_compare_equal)"; + + debian.have_aptitude:: + package_add_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes install"; + package_list_update_command => "/usr/bin/aptitude update"; + package_delete_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes remove"; + package_update_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes install"; + package_patch_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes install"; + package_verify_command => "/usr/bin/aptitude show"; + package_noverify_regex => "(State: not installed|E: Unable to locate package .*)"; + + package_patch_list_command => "/usr/bin/aptitude --assume-yes --simulate --verbose full-upgrade"; + package_patch_name_regex => "^Inst\s+(\S+)\s+.*"; + package_patch_version_regex => "^Inst\s+\S+\s+\[?\(?([^\],\s]+).*"; + + debian.!have_aptitude:: + package_add_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; + package_list_update_command => "$(debian_knowledge.call_apt_get) update"; + package_delete_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes remove"; + package_update_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; + package_patch_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; + package_verify_command => "$(debian_knowledge.call_dpkg) -s"; + package_noverify_returncode => "1"; + + package_patch_list_command => "$(debian_knowledge.call_apt_get) --just-print dist-upgrade"; + package_patch_name_regex => "^Inst\s+(\S+)\s+.*"; + package_patch_version_regex => "^Inst\s+\S+\s+\[?\(?([^\],\s]+).*"; + + 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"; + + 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"; + + 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).*"; + + archlinux:: + package_changes => "bulk"; + package_list_command => "/usr/bin/pacman -Q"; + package_list_name_regex => "(.*)\s+.*"; + package_list_version_regex => ".*\s+(.*)"; + package_installed_regex => ".*"; + package_name_convention => "$(name)"; + package_list_update_ifelapsed => "240"; + 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"; +} + +# Same as ncf_generic with version in package name +# DEPRECATED +body package_method ncf_generic_version +{ + SuSE:: + 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_command => "/usr/bin/zypper --non-interactive refresh"; + package_list_update_ifelapsed => "240"; # 4 hours + package_installed_regex => "i.*"; + package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*"; + package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; + package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; + package_patch_name_regex => "[^|]+\|\s+([^\s]+).*"; + package_patch_version_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*"; + package_name_convention => "$(name)=$(version)"; + 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 ${redhat_knowledge.yum_options} 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)-$(version)"; + package_list_update_command => "/usr/bin/yum ${redhat_knowledge.yum_options} check-update"; + 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 ${redhat_knowledge.yum_options} -y install"; + package_update_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; + package_patch_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; + package_delete_command => "/bin/rpm -e --nodeps --allmatches"; + package_verify_command => "/bin/rpm -V"; + package_version_less_command => "$(redhat_knowledge.rpm_compare_less)"; + package_version_equal_command => "$(redhat_knowledge.rpm_compare_equal)"; + + debian:: + package_changes => "bulk"; + package_list_command => "$(debian_knowledge.call_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)=$(version)"; + package_list_update_ifelapsed => "240"; # 4 hours + + # make correct version comparisons + package_version_less_command => "$(debian_knowledge.dpkg_compare_less)"; + package_version_equal_command => "$(debian_knowledge.dpkg_compare_equal)"; + + + debian.have_aptitude:: + package_add_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes install"; + package_list_update_command => "/usr/bin/aptitude update"; + package_delete_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes remove"; + package_update_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes install"; + package_patch_command => "$(debian_knowledge.call_aptitude) $(debian_knowledge.dpkg_options) --assume-yes install"; + package_verify_command => "/usr/bin/aptitude show"; + package_noverify_regex => "(State: not installed|E: Unable to locate package .*)"; + + package_patch_list_command => "/usr/bin/aptitude --assume-yes --simulate --verbose full-upgrade"; + package_patch_name_regex => "^Inst\s+(\S+)\s+.*"; + package_patch_version_regex => "^Inst\s+\S+\s+\[?\(?([^\],\s]+).*"; + + debian.!have_aptitude:: + package_add_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; + package_list_update_command => "$(debian_knowledge.call_apt_get) update"; + package_delete_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes remove"; + package_update_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; + package_patch_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; + package_verify_command => "$(debian_knowledge.call_dpkg) -s"; + package_noverify_returncode => "1"; + + package_patch_list_command => "$(debian_knowledge.call_apt_get) --just-print dist-upgrade"; + package_patch_name_regex => "^Inst\s+(\S+)\s+.*"; + package_patch_version_regex => "^Inst\s+\S+\s+\[?\(?([^\],\s]+).*"; + + 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"; + + 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)=$(version)"; + package_add_command => "/sbin/apk add"; + package_delete_command => "/sbin/apk del"; + + 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).*"; + + archlinux:: + package_changes => "bulk"; + package_list_command => "/usr/bin/pacman -Q"; + package_list_name_regex => "(.*)\s+.*"; + package_list_version_regex => ".*\s+(.*)"; + package_installed_regex => ".*"; + package_name_convention => "$(name)"; + package_list_update_ifelapsed => "240"; + 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"; +} + +# Same as apt_get from CFEngine lib with version in package name +# DEPRECATED +body package_method apt_get_version +{ + package_changes => "bulk"; + package_list_command => "$(debian_knowledge.call_dpkg) -l"; + package_list_name_regex => "$(debian_knowledge.list_name_regex)"; + package_list_version_regex => "$(debian_knowledge.list_version_regex)"; + package_installed_regex => ".i.*"; # packages that have been uninstalled may be listed + package_name_convention => "$(name)=$(version)"; + + # set it to "0" to avoid caching of list during upgrade + package_list_update_ifelapsed => "$(common_knowledge.list_update_ifelapsed)"; + + # Target a specific release, such as backports + package_add_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; + package_list_update_command => "$(debian_knowledge.call_apt_get) update"; + package_delete_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes -q remove"; + package_update_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; + package_patch_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes install"; + package_verify_command => "$(debian_knowledge.call_dpkg) -s"; + package_noverify_returncode => "1"; + + package_patch_list_command => "$(debian_knowledge.call_apt_get) --just-print dist-upgrade"; + package_patch_name_regex => "$(debian_knowledge.patch_name_regex)"; + package_patch_version_regex => "$(debian_knowledge.patch_version_regex)"; + + # make correct version comparisons + package_version_less_command => "$(debian_knowledge.dpkg_compare_less)"; + package_version_equal_command => "$(debian_knowledge.dpkg_compare_equal)"; +} + +######################################################################## +# Install a package using rug # +######################################################################## +# DEPRECATED +body package_method rudder_rug +{ + package_changes => "individual"; + + package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\""; + 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_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"; + + 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 # +######################################################################## +# DEPRECATED +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 ${redhat_knowledge.yum_options} 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 ${redhat_knowledge.yum_options} -y install"; + package_update_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -y update"; + package_patch_command => "/usr/bin/yum ${redhat_knowledge.yum_options} -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}"; +} diff --git a/tree/20_cfe_basics/package_lib.cf b/tree/20_cfe_basics/packages.cf similarity index 99% rename from tree/20_cfe_basics/package_lib.cf rename to tree/20_cfe_basics/packages.cf index a8646ea8f..24ec3697f 100644 --- a/tree/20_cfe_basics/package_lib.cf +++ b/tree/20_cfe_basics/packages.cf @@ -345,4 +345,3 @@ bundle agent ncf_package(name, version, architecture, provider, state, options) "force failure class" usebundle => _classes_failure("${class_prefix}"); "force failure class" usebundle => _classes_failure("${old_class_prefix}"); } - diff --git a/tree/20_cfe_basics/paths.cf b/tree/20_cfe_basics/paths.cf new file mode 100644 index 000000000..012f67f2d --- /dev/null +++ b/tree/20_cfe_basics/paths.cf @@ -0,0 +1,37 @@ +##################################################################################### +# Copyright 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 . +# +##################################################################################### + +# Use rudder_curl variable if available, rather than the path[curl] +bundle common ncf_paths +{ + vars: + "path[curl]" string => "${g.rudder_curl}", + if => isvariable("g.rudder_curl"); + + "path[curl]" string => "${paths.path[curl]}", + unless => isvariable("g.rudder_curl"); + + + "all_paths" slist => getindices("path"); + "$(all_paths)" string => "$(path[$(all_paths)])"; + + classes: + "_ncf_path_exists_$(all_paths)" + expression => fileexists("$(path[$(all_paths)])"), + comment => "It's useful to know if $(all_paths) exists on the filesystem as defined"; +} diff --git a/tree/20_cfe_basics/processes.cf b/tree/20_cfe_basics/processes.cf new file mode 100644 index 000000000..5b55f13b0 --- /dev/null +++ b/tree/20_cfe_basics/processes.cf @@ -0,0 +1,34 @@ +##################################################################################### +# Copyright 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 . +# +##################################################################################### + +# WARNING !!! +# For new class prefix migration only, this will be removed when migration is over +body process_count any_count_two(cl, cl2) +{ + match_range => "0,0"; + out_of_range_define => { "$(cl)", "$(cl2)" }; +} + +####################################################### +# Match all variants of cron processes +# DEPRECATED +body process_select cron_bin +{ + command => "(/usr/sbin/)?crond?( -n| -f| -l notice)*"; + process_result => "command"; +} diff --git a/tree/20_cfe_basics/services.cf b/tree/20_cfe_basics/services.cf new file mode 100644 index 000000000..aaf4098e8 --- /dev/null +++ b/tree/20_cfe_basics/services.cf @@ -0,0 +1,351 @@ +##################################################################################### +# Copyright 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 . +# +##################################################################################### + +# defines ncf_services_${service}_${action} +# +# Standard actions are: +# +# * start +# * stop +# * restart +# * reload (with an alias to refresh) +# * is-active (with an alias to status) +# * is-active-process (in this case, the "service" parameter is the regex to match againt process list) +# * enable +# * disable +# * is-enabled +# +# When using service, init.d or systemd, any unkown action will be passed as is to the command +# wich allows support for try-restart, force-reload, etc. +# +# This bundle can be seen as a kind of service_bundle, but: +# +# * No concept of state, every call is an action that will be executed. State must be implemented at higher level. +# * More supported actions, services promises are limited to start/stop/enable/disable +# * Special actions (is-*) for checks +# +bundle agent ncf_services(service, action) +{ + vars: + ########################################################################### + # All actions + ########################################################################### + + # These commands (sadly) are not completely static (as on debian 8 and upstart the outcome depends on the service) + + # systemd + pass1.!is_init_service.systemctl_utility_present:: + "action_command" string => "${paths.path[systemctl]} --no-ask-password ${action} ${service}.service"; + "method" string => "systemctl"; + + # upstart + pass1.!systemctl_utility_present.is_upstart_service:: + # non-boot + "upstart_action_cmd[start]" string => "/sbin/initctl start ${service}"; + "upstart_action_cmd[stop]" string => "/sbin/initctl stop ${service}"; + "upstart_action_cmd[restart]" string => "/sbin/initctl restart ${service}"; + "upstart_action_cmd[reload]" string => "/sbin/initctl reload ${service}"; + "upstart_action_cmd[is-active]" string => "/sbin/initctl status ${service} 2>&1 | grep -q ' start/'"; + # boot + "upstart_action_cmd[enable]" string => "${paths.path[sed]} -i '/^manual/d' /etc/init/${service}.override"; + "upstart_action_cmd[disable]" string => "${paths.path[echo]} manual >> /etc/init/${service}.override"; + # this one may not be true is it was disabled by another way + "upstart_action_cmd[is-enabled]" string => "${paths.path[grep]} -q '^manual' /etc/init/${service}.override; test $? -ne 0"; + "action_command" string => "${upstart_action_cmd[${action}]}"; + "method" string => "upstart"; + + # svcadm/svcs + pass1.!systemctl_utility_present.!is_upstart_service.svcadm_utility_present:: + # non-boot + "svc_action_cmd[start]" string => "${paths.path[svcadm]} enable -s -t ${service}"; + "svc_action_cmd[stop]" string => "${paths.path[svcadm]} disable -s -t ${service}"; + "svc_action_cmd[restart]" string => "${paths.path[svcadm]} restart -s ${service}"; + "svc_action_cmd[reload]" string => "${paths.path[svcadm]} refresh -s ${service}"; + "svc_action_cmd[is-active]" string => "${paths.path[svcs]} -H ${service} | ${paths.path[grep]} '^online'"; + # boot + "svc_action_cmd[enable]" string => "${paths.path[svcadm]} enable -s ${service}"; + "svc_action_cmd[disable]" string => "${paths.path[svcadm]} disable -s ${service}"; + "svc_action_cmd[is-enabled]" string => "${paths.path[svcs]} -l ${service} | ${paths.path[egrep]} '^enabled [ ]+(true|false \(temporary\))'"; + "action_command" string => "${svc_action_cmd[${action}]}"; + "method" string => "svcadm/svcs"; + + # Slackware + pass1.slackware:: + "method" string => "/etc/rc.d"; + + ########################################################################### + # Boot actions + ########################################################################### + + # chkconfig + pass1.is_boot_action.(!systemctl_utility_present|is_init_service).!is_upstart_service.!svcadm_utility_present.chkconfig_utility_present:: + "chkconfig_action_cmd[enable]" string => "${paths.path[chkconfig]} ${service} on"; + "chkconfig_action_cmd[disable]" string => "${paths.path[chkconfig]} ${service} off"; + "chkconfig_action_cmd[is-enabled]" string => "${paths.path[chkconfig]} --list ${service} 2>&1 | ${paths.path[grep]} -q -e 3:on -e B:on"; + "action_command" string => "${chkconfig_action_cmd[${action}]}"; + "method" string => "chkconfig"; + + # update-rc.d + # WARN: "is-enabled" will use /etc/rcX.d/ directly + pass1.is_boot_action.!is_check_action.(!systemctl_utility_present|is_init_service).!is_upstart_service.!svcadm_utility_present.!chkconfig_utility_present.update_rcd_utility_present:: + "action_command" string => "${paths.path[update_rc_d]} ${service} ${action}"; + "method" string => "update-rc.d"; + + # chitab/lsitab + pass1.is_boot_action.!systemctl_utility_present.!is_upstart_service.!svcadm_utility_present.!chkconfig_utility_present.!update_rcd_utility_present.chitab_utility_present:: + "chitab_action_cmd[enable]" string => "/usr/sbin/chitab \"`lsitab -a | grep '^${service}:' | sed 's/\([^:]*\):\([^:]*\):[^:]*:\(.*\)/\1:\2:respawn:\3/'`\""; + "chitab_action_cmd[disable]" string => "/usr/sbin/chitab \"`lsitab -a | grep '^${service}:' | sed 's/\([^:]*\):\([^:]*\):[^:]*:\(.*\)/\1:\2:off:\3/'`\""; + "lsitab_action_cmd[is-enabled]" string => "/usr/sbin/lsitab -a | ${paths.path[egrep]} '^${service}:[0-9]+:(respawn|boot|bootwait|wait|once|initdefault|sysinit):'"; + "action_command" string => "${lsitab_action_cmd[${action}]}"; + "method" string => "lsitab/chitab"; + + # /etc/rcX.d/ + pass1.is_boot_action.is_check_action.(!systemctl_utility_present|is_init_service).!is_upstart_service.!svcadm_utility_present.!chkconfig_utility_present.!chitab_utility_present.!slackware:: + "action_command" string => "${paths.path[test]} -f /etc/rc`/sbin/runlevel | ${paths.path[cut]} -d' ' -f2`.d/S??${service}"; + "method" string => "/etc/rcX.d/"; + + # Slackware boot actions are not performed by command, they are implemented in the 'methods' promises + + ########################################################################### + # Non-boot actions + ########################################################################### + + # service + # WARN: Some actions may not be supported by the init script + pass1.!is_boot_action.(!systemctl_utility_present|is_init_service).!is_upstart_service.!svcadm_utility_present.service_utility_present:: + "action_command" string => "${paths.path[service]} ${service} ${action}", + ifvarclass => "!is_check_action"; + # is-active is mapped to "status" + "action_command" string => "${paths.path[service]} ${service} status", + ifvarclass => "is_check_action"; + "method" string => "service"; + + # src + pass1.!is_boot_action.!systemctl_utility_present.!is_upstart_service.!svcadm_utility_present.!service_utility_present.startsrc_utility_present:: + "svc_action_cmd[start]" string => "/usr/bin/startsrc -s ${service}"; + "svc_action_cmd[stop]" string => "/usr/bin/stopsrc -s ${service}"; + "svc_action_cmd[restart]" string => "/usr/bin/stopsrc -s ${service} && until /usr/bin/lssrc -s ${service} | ${paths.grep} -q inoperative; do ${paths.perl} -e 'select(undef,undef,undef,.25)'; done; /usr/bin/startsrc -s ${service_name}"; + "svc_action_cmd[reload]" string => "/usr/bin/refresh -s ${service}"; + "svc_action_cmd[is-active]" string => "/usr/bin/lssrc -s ${service} | ${paths.path[grep]} -q 'active'"; + "action_command" string => "${svc_action_cmd[${action}]}"; + "method" string => "src"; + + # init.d + # WARN: Some actions may not be supported by the init script + pass1.!is_boot_action.(!systemctl_utility_present|is_init_service).!is_upstart_service.!svcadm_utility_present.!service_utility_present.!startsrc_utility_present.is_init_service:: + "action_command" string => "/etc/init.d/${service} ${action}", + ifvarclass => "!is_check_action"; + # is-active is mapped to "status" + "action_command" string => "/etc/init.d/${service} status", + ifvarclass => "is_check_action"; + "method" string => "/etc/init.d/"; + + # Slackware + pass1.slackware.!is_boot_action:: + "action_command" string => "/etc/rc.d/rc.${service} ${action}", + ifvarclass => "!is_check_action"; + # is-active is mapped to "status" + "action_command" string => "/etc/rc.d/rc.${service} status", + ifvarclass => "is_check_action"; + + # windows + # Implementation is done in services promises + windows:: + "method" string => "Windows Service Manager"; + + ########################################################################### + + any:: + "canonified_service" string => canonify("${service}"); + "canonified_action" string => canonify("${action}"); + "canonified_action_command" string => canonify("${action_command}"); + + "class_prefix" string => "ncf_services_${canonified_service}_${canonified_action}"; + + defaults: + # status is an alias to is-active (in systemd, it is not the same thing the only difference is the output, which is not kept anyway) + "actual_action" string => "is-active", if_match_regex => "status"; + + # refresh is an alias to reload + "actual_action" string => "reload", if_match_regex => "refresh"; + + classes: + + windows:: + "is_valid_action" or => { + strcmp("start", "${action}"), + strcmp("stop", "${action}"), + strcmp("restart", "${action}"), + }; + "is_restart_action" expression => strcmp("restart", "${action}"); + + any:: + "is_process_action" expression => strcmp("is-active-process", "${action}"); + + "is_boot_action" or => { + strcmp("enable", "${action}"), + strcmp("disable", "${action}"), + strcmp("is-enabled", "${action}") + }; + + "is_check_action" or => { + strcmp("is-active", "${action}"), + strcmp("is-active-process", "${action}"), + strcmp("is-enabled", "${action}") + }; + + # Due to lack of integration between upstart and init scripts, we have to make different cases. + "is_upstart_service" not => returnszero("/sbin/initctl status ${service} 2>&1 | ${paths.path[grep]} -E 'Unknown job|Unable to connect to Upstart' > /dev/null", "useshell"), + ifvarclass => "ubuntu.initctl_utility_present"; + + # Due to compatibility issues when mixing init.d/service and systemctl calls, we use the init script when present + "is_init_service" expression => fileexists("/etc/init.d/${service}"); + + pass1:: + "method_found" expression => isvariable("method"); + + ##### + # Actual command - for checks on non-windows systems + ##### + pass1.is_check_action.!windows.!is_process_action.method_found.!(slackware.is_boot_action):: + "action_ok" expression => returnszero("${action_command} 2>&1 > /dev/null", "useshell"); + + any:: + "pass3" expression => "pass2"; + "pass2" expression => "pass1"; + "pass1" expression => "any"; + + methods: + + ##### + # Actual command - for actions on non-windows systems, non using systemd, non-slackware + ##### + pass2.is_check_action.!windows.!is_process_action.method_found.action_ok.!slackware:: + "force_success_class" usebundle => _classes_success("${class_prefix}"); + + pass2.is_check_action.!windows.!is_process_action.method_found.!action_ok.!slackware:: + "force_failure_class" usebundle => _classes_failure("${class_prefix}"); + + # Method not found + pass2.(!method_found|(windows.!is_valid_action)):: + "force_failure_class" usebundle => _classes_failure("${class_prefix}"); + + # Classes for process check + pass2:: + "force_failure_process" usebundle => _classes_failure("${class_prefix}"), + ifvarclass => "${class_prefix}_checked_not_ok"; + + "force_success_process" usebundle => _classes_success("${class_prefix}"), + ifvarclass => "${class_prefix}_checked_ok"; + # Slackware boot actions + pass2.slackware.is_boot_action:: + "action" usebundle => slackware_boot_services("${service}", "${action}", "${class_prefix}"); + processes: + + ########################################################################### + # is-active-process action + ########################################################################### + + is_process_action:: + "${service}" + process_count => any_count("${class_prefix}_checked_ok"); + + "${service}" + restart_class => "${class_prefix}_checked_not_ok"; + + services: + + ########################################################################### + # Windows - only non-boot actions + ########################################################################### + + ##### + # Actual command - for actions on windows systems + ##### + # Restart causes the agent to fail, so we must replace it by stop and start + windows.is_valid_action.!is_restart_action:: + "${service}" + service_policy => "${action}", + classes => classes_generic("${class_prefix}"); + + windows.is_restart_action:: + "${service}" + service_policy => "stop", + classes => classes_generic("${class_prefix}_stop_service"); + + "${service}" + service_policy => "start", + classes => classes_generic("${class_prefix}"), + ifvarclass => "${class_prefix}_stop_service_ok"; + + commands: + ##### + # Actual command - for actions on non-windows systems + ##### + # We need to use our own commands: implementation here rather than calling command_execution + # because of a CFEngine bug (https://dev.cfengine.com/issues/5840) that causes systemctl + # to fail if it can't find /dev/tty, which is the case unless using no_output => true + # It also avoids reporting on command_execution for all platforms + pass2.!is_check_action.!windows.!is_process_action.method_found.!(slackware.is_boot_action):: + "${action_command}" + contain => in_shell_and_silent, + classes => classes_generic("${class_prefix}"); + + reports: + + pass3.error.!method_found:: + "${configuration.error} Could not find a supported service management method on this system"; + pass3.error.!is_valid_action:: + "${configuration.error} The ${action} action is not supported on Windows (use 'start', 'stop' or 'restart')"; + + pass3.info.method_found.(!windows|is_valid_action):: + "${configuration.info} Executing ${action} on ${service} using the ${method} method"; + + pass3.debug.method_found.!windows:: + "${configuration.debug} Executing: '${action_command}'"; +} + +bundle agent slackware_boot_services(service, action, class_prefix) +{ + vars: + "canon_service" string => canonify("${service}"); + + classes: + + "action_enable" expression => strcmp("enable", ${action}); + "action_disable" expression => strcmp("disable", ${action}); + "action_is_enabled" expression => strcmp("is-enabled", ${action}); + + methods: + + action_disable:: + "chmod 644" usebundle => perm_on_file("/etc/rc.d/rc.${service}", "644", "${class_prefix}"); + + action_enable:: + "chmod 755" usebundle => perm_on_file("/etc/rc.d/rc.${service}", "755", "${class_prefix}"); + "block in init scripts" usebundle => service_block_rc_d("${service}", "${class_prefix}"); + + action_is_enabled:: + "enable dry run" usebundle => push_dry_run_mode("true"); + "chmod 755" usebundle => perm_on_file("/etc/rc.d/rc.${service}", "755", "${canon_service}_init_script_execmod"); + "block in init scripts" usebundle => service_block_rc_d("${service}", "${class_prefix}"), + ifvarclass => "${canon_service}_init_script_execmod_ok"; + "ifnoexecmod, new" usebundle => _classes_copy("${canon_service}_init_script_execmod", "${class_prefix}"), + ifvarclass => "${canon_service}_init_script_execmod_not_ok"; + "disable dry run" usebundle => pop_dry_run_mode(); +} diff --git a/tree/20_cfe_basics/storage.cf b/tree/20_cfe_basics/storage.cf new file mode 100644 index 000000000..dba128a22 --- /dev/null +++ b/tree/20_cfe_basics/storage.cf @@ -0,0 +1,28 @@ +##################################################################################### +# Copyright 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 . +# +##################################################################################### + +######################################################################## +# 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}"; +} diff --git a/tree/20_cfe_basics/time_lib.cf b/tree/20_cfe_basics/time.cf similarity index 99% rename from tree/20_cfe_basics/time_lib.cf rename to tree/20_cfe_basics/time.cf index aa23b11aa..5927d303b 100644 --- a/tree/20_cfe_basics/time_lib.cf +++ b/tree/20_cfe_basics/time.cf @@ -16,8 +16,6 @@ # ##################################################################################### -# @agent_version >=3.6 -# # This collection of bundles manage time related calculations # # @@ -168,7 +166,6 @@ bundle agent schedule_generic(job_id, agent_periodicity, max_execution_delay, jo } - # Simple Periodic Scheduler, it raises a class on a regular perioridicity, based on a user friendly definition. # # job_id: a string to identify this job @@ -226,4 +223,3 @@ bundle agent schedule_simple_generic(job_id, agent_periodicity, any:: "any" usebundle => schedule_generic("${job_id}", "${agent_periodicity}", "${max_execution_delay}", "${job_periodicity}", "${minutes_from_start}"); } -