###############################################################################
#
#   update.cf - Basic Update Policy for Community
#
###############################################################################

body common control
{
 bundlesequence => { "cfe_internal_update" };
 version => "Community Update.cf 3.4.1";
}

#############################################################################

body agent control
{
 ifelapsed => "1";
 skipidentify => "true";
}

#############################################################################

bundle agent cfe_internal_update
{
 vars:

   "inputs_dir"         string => translatepath("$(sys.workdir)/inputs"),
                       comment => "Directory containing Cfengine policies",
                        handle => "update_vars_inputs_dir";

   "modules_dir"        string => translatepath("$(sys.workdir)/modules"),
                       comment => "Directory containing CFEngine modules",
                        handle => "update_vars_modules_dir";

   "ppkeys_file"        string => translatepath("$(sys.workdir)/ppkeys/localhost.pub"),
                       comment => "Path to public key file",
                        handle => "update_vars_ppkeys_file";

   "file_check"         string => translatepath("$(inputs_dir)/promises.cf"),
                       comment => "Path to a policy file",
                        handle => "update_vars_file_check";

   "master_location"    string => "/var/cfengine/masterfiles",
                       comment => "The master cfengine policy directory on the policy host",
                        handle => "update_vars_master_location";

   "agents" slist => {
                      "cf-agent",
                      "cf-execd",
                      "cf-key",
                      "cf-monitord",
                      "cf-promises",
                      "cf-report",
                      "cf-runagent",
                      "cf-serverd",
                     },
            comment => "List of CFEngine binaries",
             handle => "update_vars_agents";

#

 classes:

   "have_ppkeys"   expression => fileexists("$(ppkeys_file)"),
                      comment => "Check for /var/cfengine/ppkeys/localhost.pub",
                       handle => "update_classes_have_ppkeys";

   "files_ok"      expression => fileexists("$(file_check)"),
                      comment => "Check for /var/cfengine/masterfiles/promises.cf",
                       handle => "update_classes_files_ok";

#

 processes:

  files_ok::

   "cf-serverd"  restart_class => "start_server",
                       comment => "Monitor cf-serverd process",
                        handle => "update_processes_cf_serverd";

   "cf-monitord" restart_class => "start_monitor",
                       comment => "Monitor cf-monitord process",
                        handle => "update_processes_cf_monitord";

  files_ok.!windows::

   "cf-execd"    restart_class => "start_exec",
                       comment => "Monitor cf-execd process",
                        handle => "update_processes_cf_execd";

#

 commands:

  start_server::

   "$(sys.cf_serverd)"
      comment => "Start cf-serverd process",
       handle => "update_commands_start_cf_serverd";

  start_monitor::

   "$(sys.cf_monitord)"
      comment => "Start cf-monitord process",
       handle => "update_commands_start_cf_monitord";

  !windows.start_exec::

   "$(sys.cf_execd)"
      comment => "Start cf-execd process",
       handle => "update_commands_start_cf_execd_not_windows";

  !have_ppkeys::

   "$(sys.cf_key)",
      comment => "Generate cfengine encryption keys if necessary",
       handle => "update_commands_generate_keys";

#

 files:

  !am_policy_hub::  # policy hub should not alter inputs/ uneccessary

   "$(inputs_dir)/cf_promises_validated"
        comment => "Check whether a validation stamp is available for a new policy update to reduce the distributed load",
         handle => "update_files_check_valid_update",
      copy_from => u_rcp("$(master_location)/cf_promises_validated","$(sys.policy_hub)"),
         action => u_immediate,
        classes => u_if_repaired("validated_updates_ready");

   "$(modules_dir)"
           comment => "Always update modules files on client side",
            handle => "update_files_update_modules",
         copy_from => u_rcp("$(modules_dir)","$(sys.policy_hub)"),
      depth_search => u_recurse("inf"),
             perms => u_m("755"),
            action => u_immediate;

  am_policy_hub|validated_updates_ready::  # policy hub should always put masterfiles in inputs in order to check new policy

   "$(inputs_dir)"
           comment => "Copy policy updates from master source on policy server if a new validation was acquired",
            handle => "update_files_inputs_dir",
         copy_from => u_rcp("$(master_location)","$(sys.policy_hub)"),
      depth_search => u_recurse("inf"),
      file_select  => u_input_files,
            action => u_immediate,
           classes => u_if_repaired("update_report");

  !windows::

   "$(sys.workdir)/bin"
           comment => "Make sure cfengine binaries have right file permissions",
            handle => "update_files_sys_workdir_bin",
             perms => u_m("755"),
      depth_search => u_recurse_basedir("inf"),
            action => u_immediate;

   "$(sys.workdir)/lib"
           comment => "Make sure cfengine libraries have right file permissions",
            handle => "update_files_sys_workdir_lib",
             perms => u_shared_lib_perms,
      depth_search => u_recurse_basedir("inf"),
            action => u_immediate;

  am_policy_hub::

   "$(master_location)/."
           comment => "Make sure masterfiles folder has right file permissions",
            handle => "update_files_sys_workdir_masterfiles",
             perms => u_m("644"),
      depth_search => u_recurse_basedir("inf"),
            action => u_immediate;
}

#########################################################
# Self-contained bodies from the lib to avoid dependencies
#########################################################

body perms u_m(p)
{
 mode  => "$(p)";
}

#########################################################

body perms u_shared_lib_perms
{
 !hpux::
   mode => "0644";
 hpux::
   mode => "0755";  # Mantis 1114, Redmine 1179
}

#########################################################

body file_select u_cf3_files
{
 leaf_name => { "cf-.*" };
 file_result => "leaf_name";
}

#########################################################

body file_select u_input_files
{
 leaf_name => { ".*.cf",".*.dat",".*.txt" };
 file_result => "leaf_name";
}

#########################################################

body copy_from u_rcp(from,server)
{
 source      => "$(from)";
 compare     => "digest";
 trustkey    => "false";

!am_policy_hub::

 servers => { "$(server)" };
}

#########################################################

body copy_from u_cp_nobck(from)
{
 source      => "$(from)";
 compare     => "digest";
 copy_backup => "false";
}

#########################################################

body action u_immediate
{
 ifelapsed => "0";
}

#########################################################

body depth_search u_recurse(d)
{
 depth => "$(d)";
 exclude_dirs => { "\.svn", "\.git" };
}

#########################################################

body depth_search u_recurse_basedir(d)
{
 include_basedir => "true";
 depth => "$(d)";
 exclude_dirs => { "\.svn", "\.git" };
}

#########################################################

body classes u_if_repaired(x)
{
 promise_repaired => { "$(x)" };
}

#########################################################

body link_from u_ln_s(x)
{
link_type => "symlink";
source => "$(x)";
when_no_source => "force";
}

#########################################################

body delete u_tidy
{
dirlinks => "delete";
rmdirs   => "true";
}
