diff --git a/tree/20_cfe_basics/files.cf b/tree/20_cfe_basics/files.cf index 6307fca7..6ecaa16e 100644 --- a/tree/20_cfe_basics/files.cf +++ b/tree/20_cfe_basics/files.cf @@ -555,6 +555,18 @@ body copy_from ncf_remote_cp_method(from, server, method) copy_backup => "timestamp"; } +body copy_from ncf_remote_cp_purge(from, server, method) +{ + servers => { "${server}" }; + source => "${from}"; + type_check => "true"; + portnumber => "${system_common.community_port}"; + compare => "${method}"; + encrypt => "true"; + copy_backup => "timestamp"; + purge => "true"; +} + # DEPRECATED #server may be a list body copy_from cp(from,server) diff --git a/tree/30_generic_methods/sharedfile_from_any.cf b/tree/30_generic_methods/sharedfile_from_any.cf new file mode 100644 index 00000000..b9e001db --- /dev/null +++ b/tree/30_generic_methods/sharedfile_from_any.cf @@ -0,0 +1,92 @@ +##################################################################################### +# Copyright 2024 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 Sharedfile from any +# @description This method retrieves a file shared from other Rudder node +# @documentation This method retrieves a file shared from many Rudder node using a unique file identifier. +# +# The files will be downloaded using native agent protocol and all copied into a single directory. +# The destination path must be the complete absolute path of the destination directory. +# The destination files will be named . +# The destination directoty will purged +# +# See [sharedfile_to_node](#_sharedfile_to_node) for a complete example. +# +# @parameter file_id Unique name that was used to identify the file on the sender +# @parameter_constraint file_id "regex" : "^[A-z0-9._-]+$" +# @parameter file_path Where to put the file content +# +# @class_prefix sharedfile_from_any +# @class_parameter file_id +# @agent_support = ["cfengine-community"] + +bundle agent sharedfile_from_any(file_id, file_path) +{ + vars: + "old_class_prefix" string => canonify("sharedfile_from_any${file_id}"); + "args" slist => { "${file_id}", "${file_path}" }; + "report_param" string => join("_", args); + "full_class_prefix" string => canonify("sharedfile_from_any${report_param}"); + "class_prefix" string => string_head("${full_class_prefix}", "1000"); + + "temp_dir" string => "/var/rudder/tmp/shared-files"; + pass1:: + # full path of remporary files + "files" slist => findfiles("${temp_dir}/*/${file_id}"); + # array of name of files + "file_names[${files}]" string => regex_replace("${files}", "${temp_dir}/(.*)/(.*)", "$2.$1", ""); + # slist of name of files + "name_list" slist => getvalues("file_names"); + + classes: + "pass2" expression => "pass1"; + "pass1" expression => "any"; + + files: + # first synchronize all shared-files in a temporary directory + "${temp_dir}/" + copy_from => ncf_remote_cp_purge("/var/rudder/shared-files/${g.uuid}/files/", "${sys.policy_hub}", "digest"), + depth_search => recurse("2"), + classes => classes_generic_two("step1_${old_class_prefix}", "step1_${class_prefix}"); + pass2:: + # then extract all files with this specific file_id + "${file_path}/${file_names[${files}]}" + copy_from => ncf_local_cp_method("${name_list}", "mtime"), + create => "true", + classes => classes_generic_two("step2_${old_class_prefix}", "step2_${class_prefix}"); + # finally remove files with the same file_id that don't exist anymore + "${file_path}" + delete => tidy, + depth_search => recurse("1"), + file_select => include_exclude("${file_id}", @{name_list}), + classes => classes_generic_two("step3_${old_class_prefix}", "step3_${class_prefix}"); + + methods: + pass2:: + "combine_old" usebundle => _classes_combine_three("step1_${old_class_prefix}", "step2_${old_class_prefix}", "step3_${old_class_prefix}", "${old_class_prefix}"); + "combine_new" usebundle => _classes_combine_three("step1_${class_prefix}", "step2_${class_prefix}", "step3_${class_prefix}" , "${class_prefix}"); + "report" usebundle => _log_v3("Retrieving ${file_id} from other nodes into ${file_path}", "${file_id}", "${old_class_prefix}", "${class_prefix}", @{args}); +} + +body file_select include_exclude(base, names) +{ + leaf_name => { @{names} }; + path_name => { ".*/${base}\..*$" }; + file_result => "path_name.!leaf_name"; +} +