#  Copyright 2021 Northern.tech AS

#  This file is part of CFEngine 3 - written and maintained by Northern.tech AS.

#  This program is free software; you can redistribute it and/or modify it
#  under the terms of the GNU General Public License as published by the
#  Free Software Foundation; version 3.

#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA

# To the extent this program is licensed as part of the Enterprise
# versions of Cfengine, the applicable Commercial Open Source License
# (COSL) may apply to this file if you as a licensee so wish it. See
# included file COSL.txt.

# This example shows how to use the missing_ok attribute in copy from bodies. If
# the source file is missing, the promise will be seen to be a promise kept
# instead of a failure. The exception is that a remote copy that fails to make a
# connection to the remote server will still be seen as a promise failure.

#+begin_src cfengine3
bundle agent main
{
  files:
    "/tmp/copied_from_missing_ok"
      copy_from => missing_ok( "/var/cfengine/masterfiles/missing" ),
      classes => results("bundle", "copy_from_missing_ok");

  reports:
    "$(with)"
      with => string_mustache( "{{%-top-}}", sort( classesmatching( "copy_from_.*" ), lex));
}
body copy_from missing_ok( file_path )
{
  source => "$(file_path)";
  missing_ok => "true";

    # Run with these classes to try remote copies
    remote_copy_self::
        servers => { "127.0.0.1" };

    remote_copy_policy_hub::
        servers => { $(sys.policy_hub) };
}
body classes results(scope, class_prefix)
{
  scope => "$(scope)";

  promise_kept => { "$(class_prefix)_reached",
                    "$(class_prefix)_kept" };

  promise_repaired => { "$(class_prefix)_reached",
                        "$(class_prefix)_repaired" };

  repair_failed => { "$(class_prefix)_reached",
                     "$(class_prefix)_error",
                     "$(class_prefix)_not_kept",
                     "$(class_prefix)_failed" };

  repair_denied => { "$(class_prefix)_reached",
                     "$(class_prefix)_error",
                     "$(class_prefix)_not_kept",
                     "$(class_prefix)_denied" };

  repair_timeout => { "$(class_prefix)_reached",
                      "$(class_prefix)_error",
                      "$(class_prefix)_not_kept",
                      "$(class_prefix)_timeout" };
}
#+end_src
#@ In the above example `/tmp/copied_from_missing_ok` promises to be a copy of the local file
#@ `/var/cfengine/masterfiles/missing`. In the `missing_ok` `copy_from` body
#@ `missing_ok` is set to true. This causes the promise to be considered kept if
#@ the source file is missing. The `results` classes body is used to define bundle
#@ scoped classes prefixed with `copy_from_missing_ok`. The `reports` promise
#@ outputs a sorted list of the classes defined starting with `copy_from_`.
#+begin_src example_output
#@ ```
#@ R: [
#@   "copy_from_missing_ok_kept",
#@   "copy_from_missing_ok_reached"
#@ ]
#@ ```
#+end_src
#@ We can see in the output that the class defined for copying a local file that
#@ does not exist is seen to be a promise kept.