diff --git a/bin/cdist-config b/bin/cdist-config index 946c88b4..4cad1924 100755 --- a/bin/cdist-config +++ b/bin/cdist-config @@ -42,8 +42,9 @@ __cdist_abs_myname="$__cdist_abs_mydir/$__cdist_myname" : ${__cdist_name_bin:=bin} : ${__cdist_name_code:=code} -: ${__cdist_name_code_finished:=.codedone} +: ${__cdist_name_code_finished:=codedone} : ${__cdist_name_conf_dir:=conf} +: ${__cdist_name_dot_cdist:=.cdist} : ${__cdist_name_explorer:=explorer} : ${__cdist_name_gencode:=gencode} : ${__cdist_name_gencode_local:=local} @@ -53,9 +54,9 @@ __cdist_abs_myname="$__cdist_abs_mydir/$__cdist_myname" : ${__cdist_name_init:=init} : ${__cdist_name_manifest:=manifest} : ${__cdist_name_object:=object} -: ${__cdist_name_object_finished:=.done} +: ${__cdist_name_object_finished:=done} : ${__cdist_name_object_id:=object_id} -: ${__cdist_name_object_source:=.source} +: ${__cdist_name_object_source:=source} : ${__cdist_name_out_dir:=out} : ${__cdist_name_parameter:=parameter} : ${__cdist_name_parameter_required:=required} @@ -133,7 +134,7 @@ __cdist_tmp_file=$(mktemp "$__cdist_tmp_dir/cdist.XXXXXXXXXXXX") : ${__cdist_remote_out_object_base_dir:=$__cdist_remote_out_dir/$__cdist_name_object} ################################################################################ -# Function list +# Internal functions # __cdist_debug_echo() { @@ -142,6 +143,12 @@ __cdist_debug_echo() fi } +__cdist_exec_fail_on_error() +{ + sh -e "$@" + [ "$?" -eq 0 ] || __cdist_exit_err "Error: $1 exited non-zero." +} + __cdist_exit_err() { echo "$@" >&2 @@ -169,76 +176,9 @@ __cdist_init_deploy() ln -sf "$__cdist_conf_dir" "$__cdist_local_base_dir/$__cdist_name_conf_dir" } -__cdist_type_has_explorer() -{ - # We only create output, if there's at least one explorer - # and can thus be used as a boolean ;-) - if [ -d "$(__cdist_type_explorer_dir "$1")" ]; then - ls -1 "$(__cdist_type_explorer_dir "$1")" - fi -} - -__cdist_type_dir() -{ - echo "${__cdist_type_dir}/$1" -} - -__cdist_type_explorer_dir() -{ - echo "${__cdist_type_dir}/$1/${__cdist_name_explorer}" -} - -__cdist_remote_type_explorer_dir() -{ - echo "${__cdist_remote_type_dir}/$1/${__cdist_name_explorer}" -} - -__cdist_type_gencode() -{ - echo "${__cdist_type_dir}/$1/${__cdist_name_gencode}" -} - -__cdist_type_singleton() -{ - echo "${__cdist_type_dir}/$1/${__cdist_name_singleton}" -} - -__cdist_type_parameter_dir() -{ - echo "$(__cdist_type_dir "$1")/${__cdist_name_parameter}" -} - -# Shorthand for required and optional -__cdist_type_parameter_required() -{ - echo "$(__cdist_type_parameter_dir "$1")/$__cdist_name_parameter_required" -} - -__cdist_type_parameter_optional() -{ - echo "$(__cdist_type_parameter_dir "$1")/$__cdist_name_parameter_optional" -} - -__cdist_type_from_object() -{ - echo "${1%%/*}" -} - -__cdist_object_id_from_object() -{ - echo "${1#*/}" -} - -__cdist_object_dir() -{ - __cdist_object_dir="${__cdist_out_object_dir}/$1" - echo "$__cdist_object_dir" -} - -__cdist_remote_object_dir() -{ - echo "${__cdist_remote_out_object_base_dir}/$1" -} +################################################################################ +# Object +# __cdist_object_code() { @@ -250,29 +190,20 @@ __cdist_object_code_finished() echo "$(__cdist_object_dir "$1")/${__cdist_name_code_finished}" } -__cdist_object_parameter_dir() +__cdist_object_dir() { - echo "$(__cdist_object_dir "$1")/${__cdist_name_parameter}" + echo "$(__cdist_object_base_dir "$1")/${__cdist_name_dot_cdist}" } -__cdist_remote_object_parameter_dir() +__cdist_object_base_dir() { - echo "$(__cdist_remote_object_dir "$1")/${__cdist_name_parameter}" + echo "${__cdist_out_object_dir}/$1" } -__cdist_object_require() -{ - echo "$(__cdist_object_dir "$1")/${__cdist_name_require}" -} -__cdist_object_type_explorer_dir() +__cdist_object_id_from_object() { - echo "$(__cdist_object_dir "$1")/${__cdist_name_explorer}" -} - -__cdist_remote_object_type_explorer_dir() -{ - echo "$(__cdist_remote_object_dir "$1")/${__cdist_name_explorer}" + echo "${1#*/}" } # Find objects, remove ./ and /MARKER @@ -284,32 +215,131 @@ __cdist_object_list() ( cd "${basedir}" - find . -name "$__cdist_name_object_source" | \ - sed -e 's;^./;;' -e "s;/${__cdist_name_object_source}\$;;" + find . -name "$__cdist_name_dot_cdist" | \ + sed -e 's;^./;;' -e "s;/${__cdist_name_dot_cdist}\$;;" ) +} +__cdist_object_parameter_dir() +{ + echo "$(__cdist_object_dir "$1")/${__cdist_name_parameter}" +} + +__cdist_object_require() +{ + echo "$(__cdist_object_dir "$1")/${__cdist_name_require}" +} + +__cdist_object_source_name() +{ + echo "$1/${__cdist_name_object_source}" } __cdist_object_source() { - local object_dir="$1"; shift - - cat "${object_dir}/${__cdist_name_object_source}" + cat "$(__cdist_object_source_name "$1")" } -__cdist_exec_fail_on_error() +__cdist_object_source_add() { - sh -e "$@" - [ "$?" -eq 0 ] || __cdist_exit_err "Error: $1 exited non-zero." + echo "$__cdist_manifest" >> "$(__cdist_object_source_name "$1")" +} + +__cdist_object_type_explorer_dir() +{ + echo "$(__cdist_object_dir "$1")/${__cdist_name_explorer}" +} + +################################################################################ +# Remote +# + +__cdist_remote_object_dir() +{ + echo "${__cdist_remote_out_object_base_dir}/$1" +} + +__cdist_remote_object_parameter_dir() +{ + echo "$(__cdist_remote_object_dir "$1")/${__cdist_name_parameter}" +} + +__cdist_remote_object_type_explorer_dir() +{ + echo "$(__cdist_remote_object_dir "$1")/${__cdist_name_explorer}" } +__cdist_remote_type_explorer_dir() +{ + echo "${__cdist_remote_type_dir}/$1/${__cdist_name_explorer}" +} + + +################################################################################ +# Temp clenup +# __cdist_tmp_removal() { rm -rf "${__cdist_tmp_dir}" } -################################################################################ -# Trap for tmp removal -# trap __cdist_tmp_removal EXIT + + +################################################################################ +# Type +# +__cdist_type_dir() +{ + echo "${__cdist_type_dir}/$1" +} + +__cdist_type_explorer_dir() +{ + echo "${__cdist_type_dir}/$1/${__cdist_name_explorer}" +} + +__cdist_type_from_object() +{ + echo "${1%%/*}" +} + +__cdist_type_has_explorer() +{ + # We only create output, if there's at least one explorer + # and can thus be used as a boolean ;-) + if [ -d "$(__cdist_type_explorer_dir "$1")" ]; then + ls -1 "$(__cdist_type_explorer_dir "$1")" + fi +} + +__cdist_type_gencode() +{ + echo "${__cdist_type_dir}/$1/${__cdist_name_gencode}" +} + +__cdist_type_manifest() +{ + echo "${__cdist_type_dir}/$1/${__cdist_name_manifest}" +} + +__cdist_type_parameter_dir() +{ + echo "$(__cdist_type_dir "$1")/${__cdist_name_parameter}" +} + +__cdist_type_parameter_optional() +{ + echo "$(__cdist_type_parameter_dir "$1")/$__cdist_name_parameter_optional" +} + +__cdist_type_parameter_required() +{ + echo "$(__cdist_type_parameter_dir "$1")/$__cdist_name_parameter_required" +} + +__cdist_type_singleton() +{ + echo "${__cdist_type_dir}/$1/${__cdist_name_singleton}" +} diff --git a/bin/cdist-manifest-run b/bin/cdist-manifest-run index 892f27cf..d4ea18bb 100755 --- a/bin/cdist-manifest-run +++ b/bin/cdist-manifest-run @@ -23,7 +23,7 @@ # . cdist-config -[ $# -eq 3 ] || __cdist_usage " " +[ $# -eq 2 ] || __cdist_usage " " set -u __cdist_target_host="$1"; shift @@ -33,10 +33,6 @@ __cdist_manifest="$1"; shift # Export information for cdist-type-emulator or manifest # -# This is a special variable, as being used by __cdist_object_dir -# We need to adjust it, so cdist-type-emulator writes to the right location -export __cdist_out_object_dir="$1"; shift - # Config dir should not get reset - FIXME: why did I do this? export __cdist_conf_dir @@ -57,12 +53,4 @@ cdist-type-build-emulation "${__cdist_out_type_bin_dir}" \ # prepend our path, so all cdist tools come before other tools export PATH="${__cdist_out_type_bin_dir}:$PATH" -# Sanity checks -[ -f "${__cdist_manifest}" ] \ - || __cdist_exit_err "Missing manifest ${__cdist_manifest}" -[ -x "${__cdist_manifest}" ] \ - || __cdist_exit_err "${__cdist_manifest} needs to be executable." -mkdir -p "${__cdist_out_object_dir}" \ - || __cdist_exit_err "Cannot create output dir ${__cdist_out_object_dir}" - __cdist_exec_fail_on_error "${__cdist_manifest}" diff --git a/bin/cdist-manifest-run-all b/bin/cdist-manifest-run-all index fe8263ea..ee15273c 100755 --- a/bin/cdist-manifest-run-all +++ b/bin/cdist-manifest-run-all @@ -17,14 +17,7 @@ # You should have received a copy of the GNU General Public License # along with cdist. If not, see . # -# -# For each created object -# run the manifest of the type (with object id), -# try to merge back newly created objects (otherwise fail), -# mark the object as being run -# and iterate until all objects are marked being run. -# -# +# Run all manifests # . cdist-config @@ -35,8 +28,6 @@ __cdist_target_host="$1"; shift __cdist_objects_list="${__cdist_tmp_dir}/objects_file" __cdist_new_objects_list="${__cdist_tmp_dir}/new_objects_file" -__cdist_new_objects_dir="${__cdist_tmp_dir}/new_objects_dir" - # Loop until we do not create new objects anymore # which is equal to all objects have been run @@ -48,80 +39,33 @@ while [ "$__cdist_new_objects_created" = "y" ]; do __cdist_object_list "$__cdist_out_object_dir" > "$__cdist_objects_list" # Check every object, if we need to run it - while read __cdist_object; do + while read __cdist_object_self; do # Full path to current object - __cdist_cur_object_dir="$__cdist_out_object_dir/$__cdist_object" + __cdist_cur_object_dir="$(__cdist_object_dir "$__cdist_object_self")" + # Only the id - __cdist_object_id="$(__cdist_object_id_from_object "$__cdist_object")" + __cdist_object_id="$(__cdist_object_id_from_object "$__cdist_object_self")" if [ ! -f "${__cdist_cur_object_dir}/$__cdist_name_object_finished" ]; then - echo "Checking manifest for ${__cdist_object} ..." + echo "Checking manifest for ${__cdist_object_self} ..." - __cdist_type="$(__cdist_type_from_object "$__cdist_object")" - __cdist_manifest="$__cdist_type_dir/${__cdist_type}/${__cdist_name_manifest}" + __cdist_type="$(__cdist_type_from_object "$__cdist_object_self")" + __cdist_manifest="$(__cdist_type_manifest "${__cdist_type}")" - # Make __cdist_manifest available for cdist-type-emulator - export __cdist_manifest + if [ -f "$__cdist_manifest" ]; then + if [ -x "$__cdist_manifest" ]; then + # Make __cdist_manifest available for cdist-type-emulator + export __cdist_manifest - if [ -x "${__cdist_manifest}" ]; then - echo "Executing manifest ${__cdist_manifest} ..." + echo "Executing manifest ${__cdist_manifest} ..." + # Make variables available to non-core - FIXME: beatify + export $__cdist_name_var_object="$__cdist_cur_object_dir" + export $__cdist_name_var_object_id="$__cdist_object_id" + export $__cdist_name_var_type="$(__cdist_type_dir "$__cdist_type")" - # Make variables available to non-core - export $__cdist_name_var_object="$__cdist_cur_object_dir" - export $__cdist_name_var_object_id="$__cdist_object_id" - export $__cdist_name_var_type="$(__cdist_type_dir "$__cdist_type")" - - cdist-manifest-run "$__cdist_target_host" "$__cdist_manifest" \ - "$__cdist_new_objects_dir" - - __cdist_object_list "${__cdist_new_objects_dir}" > "$__cdist_new_objects_list" - - # Verify no conflicting objects have been created - while read __cdist_new_object; do - __cdist_object_found=$(grep "^$__cdist_new_object\$" "$__cdist_objects_list" || true) - - if [ "$__cdist_object_found" ]; then - __cdist_object_source="$(cat "$(__cdist_object_dir "$__cdist_new_object")/${__cdist_name_object_source}")" - __cdist_exit_err "${__cdist_manifest}: ${__cdist_new_object} already exists (source: $__cdist_object_source)" - fi - done < "$__cdist_new_objects_list" - - # Safe harbour: We can merge all objects into main tree - # Merge = mkdir + mv parameters and source information - while read __cdist_new_object; do - [ "$__cdist_new_objects_created" = "n" ] && __cdist_new_objects_created="y" - - # where to save the newly created object - __cdist_object_dir="$__cdist_out_object_dir/$__cdist_new_object" - mkdir -p "$__cdist_object_dir" - - # Move parts of the object (CANNOT MOVE COMPLETLEY, HIERACHY!) - __cdist_new_object_dir="$__cdist_new_objects_dir/$__cdist_new_object" - - # Source - mv "${__cdist_new_object_dir}/${__cdist_name_object_source}" \ - "$__cdist_object_dir" - - # Explorer, Parameter, Require - for __cdist_object_file in \ - ${__cdist_name_explorer} \ - ${__cdist_name_parameter} \ - ${__cdist_name_require} \ - ; do - - if [ -e "${__cdist_new_object_dir}/${__cdist_object_file}" ]; then - mv "${__cdist_new_object_dir}/${__cdist_object_file}" \ - "$__cdist_object_dir" - fi - done - done < "$__cdist_new_objects_list" - - # Remove listing and objects, otherwise the next type will reuse it... - rm -rf "$__cdist_new_objects_dir" "$__cdist_new_objects_list" - else - # Be nice, warn user if manifests exists, but is not executable - if [ -f "${__cdist_manifest}" ]; then - echo "Warning ${__cdist_manifest} exists, but is not executable." >&2 + cdist-manifest-run "$__cdist_target_host" "$__cdist_manifest" + else + __cdist_exit_err "${__cdist_manifest} needs to be executable." fi fi fi diff --git a/bin/cdist-manifest-run-init b/bin/cdist-manifest-run-init index f895bafa..9f10c12c 100755 --- a/bin/cdist-manifest-run-init +++ b/bin/cdist-manifest-run-init @@ -31,4 +31,4 @@ __cdist_target_host="$1"; shift eval export $__cdist_name_var_manifest=\"\$__cdist_manifest_dir\" echo "Running initial manifest for $__cdist_target_host ..." -cdist-manifest-run "$__cdist_target_host" "$__cdist_manifest_init" "$__cdist_out_object_dir" +cdist-manifest-run "$__cdist_target_host" "$__cdist_manifest_init" diff --git a/bin/cdist-object-explorer-all b/bin/cdist-object-explorer-all index 8654b03f..692a79bb 100755 --- a/bin/cdist-object-explorer-all +++ b/bin/cdist-object-explorer-all @@ -87,7 +87,7 @@ while [ $# -gt 0 ]; do # Execute explorers cdist-run-remote "$__cdist_target_host" \ - "__object=\"$(__cdist_remote_object_dir "$__object")\"" \ + "__object=\"$(__cdist_remote_object_dir "$__object")\"" \ "__object_id=\"$__object_id\"" \ cdist-remote-explorer-run \ "$__cdist_name_var_type_explorer" \ diff --git a/bin/cdist-type-emulator b/bin/cdist-type-emulator index 9f272569..18069b44 100755 --- a/bin/cdist-type-emulator +++ b/bin/cdist-type-emulator @@ -27,94 +27,157 @@ . cdist-config set -eu +################################################################################ +# Prepare object and type +# + __cdist_type="$__cdist_myname" # Find out whether type is a singleton or regular type if [ -f "$(__cdist_type_singleton "$__cdist_type")" ]; then - __cdist_object_id="singleton" + __cdist_object_id="$__cdist_name_singleton" else [ $# -ge 1 ] || __cdist_usage " " __cdist_object_id="$1"; shift fi -echo "$__cdist_object_id" | grep -q "^${__cdist_sane_regexp}\$" || \ +# Verify object id +__cdist_object_id_sane=$(echo "$__cdist_object_id" | grep "^${__cdist_sane_regexp}\$") +if [ -z "$__cdist_object_id_sane" ]; then __cdist_usage "Insane object id, ${__cdist_object_id}." - -# Remove double slash if id begins with / -if [ "$(echo $__cdist_object_id | grep "^/")" ]; then - __cdist_object="${__cdist_type}${__cdist_object_id}" -else - __cdist_object="${__cdist_type}/${__cdist_object_id}" fi -__cdist_ddir="$(__cdist_object_dir "$__cdist_object")" -__cdist_parameter_dir="$(__cdist_object_parameter_dir "$__cdist_object")" +# Prevent double slash if id begins with / +if [ "$(echo $__cdist_object_id | grep "^/")" ]; then + __cdist_object_self="${__cdist_type}${__cdist_object_id}" +else + __cdist_object_self="${__cdist_type}/${__cdist_object_id}" +fi + +################################################################################ +# Internal quirks +# # Append id for error messages __cdist_myname="$__cdist_myname ($__cdist_object_id)" -if [ -e "${__cdist_ddir}" ]; then - source="$(__cdist_object_source "${__cdist_ddir}")" - __cdist_exit_err "${__cdist_object} already exists (source: $source)" -fi +################################################################################ +# Create object in tmpdir first +# -mkdir -p "${__cdist_ddir}" +# Save original destination +__cdist_out_object_dir_orig="$__cdist_out_object_dir" + +# Store to tmp now +__cdist_out_object_dir="$__cdist_tmp_dir" + +__cdist_object_dir="$(__cdist_object_dir "$__cdist_object_self")" + +# Record source +mkdir -p "${__cdist_object_dir}" +__cdist_object_source_add "${__cdist_object_dir}" + +# Record parameter +__cdist_parameter_dir="$(__cdist_object_parameter_dir "$__cdist_object_self")" mkdir -p "${__cdist_parameter_dir}" -# Record (correct ;-) source -echo "${__cdist_manifest}" > "${__cdist_ddir}/${__cdist_name_object_source}" - -# Record parameters to tmpdir -tempparameter="${__cdist_tmp_dir}/${__cdist_name_parameter}" -mkdir -p "$tempparameter" - while [ $# -gt 0 ]; do opt="$1"; shift echo "$opt" | grep -q "^--${__cdist_sane_regexp}\$" || \ __cdist_usage "Provide sane options" - opt_file="$(echo $opt | sed 's/^--//')" + opt_file="${opt#--}" [ $# -ge 1 ] || __cdist_usage "Missing value for $opt" value="$1"; shift - echo "${value}" > "${tempparameter}/${opt_file}" + echo "${value}" > "${__cdist_parameter_dir}/${opt_file}" done -# Ensure required parameters are given -if [ -f "$(__cdist_type_parameter_required "$__cdist_type")" ]; then - while read required; do - if [ ! -f "${tempparameter}/${required}" ]; then - __cdist_usage "Missing required parameter $required" - fi - - mv "${tempparameter}/${required}" "${__cdist_parameter_dir}" - done < "$(__cdist_type_parameter_required "$__cdist_type")" -fi - -# Allow optional parameters -if [ -f "$(__cdist_type_parameter_optional "$__cdist_type")" ]; then - while read optional; do - if [ -f "${tempparameter}/${optional}" ]; then - mv "${tempparameter}/${optional}" "${__cdist_parameter_dir}" - fi - done < "$(__cdist_type_parameter_optional "$__cdist_type")" -fi - -# Error out on other paramaters -cd "${tempparameter}" -other="$(ls)" - -if [ "$other" ]; then - __cdist_usage "Unsupported parameter: $other" -fi - # Record requirements # it's fine, if it's not set set +u for requirement in $require; do - echo $requirement >> "$(__cdist_object_require "$__cdist_object")" - echo Recording: $__cdist_object requires $requirement + echo $requirement >> "$(__cdist_object_require "$__cdist_object_self")" + echo Object $__cdist_object_self requires $requirement done +set -u + +################################################################################ +# Check newly created object +# + +# +# Ensure required parameters are given +# +if [ -f "$(__cdist_type_parameter_required "$__cdist_type")" ]; then + while read required; do + if [ ! -f "${__cdist_parameter_dir}/${required}" ]; then + __cdist_usage "Missing required parameter $required" + fi + done < "$(__cdist_type_parameter_required "$__cdist_type")" +fi + +# +# Ensure that only optional or required parameters are given +# + +if [ -f "$(__cdist_type_parameter_optional "$__cdist_type")" ]; then + cat "$(__cdist_type_parameter_optional "$__cdist_type")" > \ + "$__cdist_tmp_file" +fi + +if [ -f "$(__cdist_type_parameter_required "$__cdist_type")" ]; then + cat "$(__cdist_type_parameter_required "$__cdist_type")" >> \ + "$__cdist_tmp_file" +fi + +cd "$__cdist_parameter_dir" +for parameter in $(ls -1); do + is_valid=$(grep "^$parameter\$" "$__cdist_tmp_file") + + [ "$is_valid" ] || "Unknown parameter $parameter" +done + +################################################################################ +# Merge object +# +# Restore original destination +__cdist_out_object_dir="$__cdist_out_object_dir_orig" + +__cdist_new_object_dir="$(__cdist_object_dir "$__cdist_object_self")" + +# +# If the object already exists and is exactly the same, merge it. Otherwise fail. +# +if [ -e "${__cdist_new_object_dir}" ]; then + # Allow diff to fail + set +e + diff -ru "${__cdist_object_dir}" "${__cdist_new_object_dir}" \ + > "$__cdist_tmp_file"; ret=$? + set -e + + if [ "$ret" != 0 ]; then + # Go to standard error + exec >&2 + echo "${__cdist_object_self} already exists differently." + echo "Recorded source(s):" + __cdist_object_source "${__cdist_new_object_dir}" + echo "Differences:" + cat "$__cdist_tmp_file" + __cdist_exit_err "Aborting due to object conflict." + fi + + # Add ourselves, if we're compatible + __cdist_object_source_add "${__cdist_new_object_dir}" +else + # + # Move object into tree: + # Create full path minus .cdist and move .cdist + # + __cdist_new_object_base_dir="$(__cdist_object_base_dir "$__cdist_object_self")" + mkdir -p "$__cdist_new_object_base_dir" + mv "$__cdist_object_dir" "$__cdist_new_object_base_dir" +fi diff --git a/doc/changelog b/doc/changelog index f120e47d..25459951 100644 --- a/doc/changelog +++ b/doc/changelog @@ -1,5 +1,7 @@ -1.3.3: +1.4: * Add --recursive to __directory + * Move cdist generated stuff to .cdist of object + * Allow objects to be redefined 1.3.2: 2011-03-21 * Add --source to __motd diff --git a/doc/dev/todo/niconext b/doc/dev/todo/niconext index 6179c017..bf13881e 100644 --- a/doc/dev/todo/niconext +++ b/doc/dev/todo/niconext @@ -1,2 +1,3 @@ -- think about using .cdist for meta information? - - otherwise: parameter, gencode-local, etc. are not valid object id stuff +Document redefine behaviour +release cdist 1.4.0 + perhaps include __self diff --git a/doc/dev/todo/post-1.3 b/doc/dev/todo/post-1.3 index 301dfdb2..ec186d3a 100644 --- a/doc/dev/todo/post-1.3 +++ b/doc/dev/todo/post-1.3 @@ -3,6 +3,7 @@ Core: - support $__self = relative_type/object_id - .cdist - cache + - display changes if object cannot be merged to user Cache: Assume you want to configure stuff one host ("monitor node"), @@ -31,3 +32,4 @@ Types to be written/extended: - regexp replace (can probably cover all?) -> aka sed. - __cron +