#######################################################
#
# Test packagesmatching()
#
# IMPORTANT!! This test depends on
# 11_packagesmatching.cf running first. This is because
# we need a fresh test directory with an empty package
# cache in order to test that packagesmatching updates
# that cache. If we install the package in the same
# policy, then the cache is already filled and the test
# is useless.
# Running a sub invocation does not work, because it
# still uses the same cache on disk.
#
#######################################################

body common control
{
      inputs => { "../../packages-info.cf.sub",
                  "../../meta_skip.cf.sub",
                  "../../../dcs.sub.cf",
                  "../../../../../inventory/any.cf",
                  "../../../../../$(sys.local_libdir)/stdlib.cf",
                  "../../../../../$(sys.local_libdir)/packages.cf",
                };
      bundlesequence  => { default("$(this.promise_filename)") };
      version => "1.0";
}

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

bundle agent init
{
  packages:
    # Old way of forcing package updates, for the legacy packages promise.
    debian::
      "cfe_internal_non_existing_package"
      package_policy => "add",
      package_method => inventory_apt_get($(cfe_autorun_inventory_packages.refresh)),
      action => if_elapsed_day;

    redhat::
      "cfe_internal_non_existing_package"
      package_policy => "add",
      package_method => inventory_yum_rpm($(cfe_autorun_inventory_packages.refresh)),
      action => if_elapsed_day;

  vars:
      "package_name" string => "$(p.name[1])";
}

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

bundle agent test
{
  vars:
      "all_packages" data => packagesmatching("$(init.package_name)",
                             ".*", ".*", ".*");
}

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

bundle agent check
{
  classes:
    any::
      "function_ok" expression => strcmp("$(test.all_packages[0])", "$(init.package_name)");
      "file1_ok" expression => fileexists("$(sys.workdir)/state/software_packages.csv");
      "file1_size_ok" not => strcmp(filestat("$(sys.workdir)/state/software_packages.csv", "size"), "0");
    enterprise::
      "file2_ok" expression => fileexists("$(sys.workdir)/state/software_patches_avail.csv");
      "file2_size_ok" not => strcmp(filestat("$(sys.workdir)/state/software_patches_avail.csv", "size"), "0");

    !enterprise::
      "ok" and => { "function_ok", "file1_ok", "file1_size_ok" };
    enterprise::
      "ok" and => { "function_ok", "file1_ok", "file2_ok", "file1_size_ok", "file2_size_ok" };

  reports:
    DEBUG::
      "packagesmatching: $(test.all_packages[0])";
    DEBUG.!function_ok::
      "function_ok not set";
    DEBUG.!file1_ok::
      "file1_ok not set";
    DEBUG.!file2_ok::
      "file2_ok not set";
    DEBUG.!file1_size_ok::
      "file1_size_ok not set";
    DEBUG.!file2_size_ok::
      "file2_size_ok not set";

    ok::
      "$(this.promise_filename) Pass";
    !ok::
      "$(this.promise_filename) FAIL";
}
body package_method inventory_apt_get(update_interval)
# @depends debian_knowledge
# @brief APT installation package method for inventory purposes only
# @param update_interval how often to update the package and patch list
#
# This package method is a copy of the yum_rpm method just for
# inventory purposes.
#
# This package method interacts with the APT package manager through
# `apt-get`.  It will never run "apt-get update" but is otherwise
# exactly like the `apt_get` package method and *may* use the network
# to install packages, as APT may decide.
{
      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 => $(update_interval);

      # Target a specific release, such as backports
      package_add_command => "$(debian_knowledge.call_apt_get) --help >/dev/null 2>&1 ; /bin/true";
      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)";
}

body package_method inventory_yum_rpm(update_interval)
# @depends common_knowledge redhat_knowledge rpm_knowledge
# @brief Yum+RPM installation method for inventory purposes only
# @param update_interval how often to update the package and patch list
#
# This package method is a copy of the yum_rpm method just for
# inventory purposes.
#
# It will never run "yum update" but is otherwise exactly like the
# `yum_rpm()` package method and *may* use the network to install
# packages, as Yum may decide.
{
      package_changes => "bulk";
      package_list_command => "$(rpm_knowledge.call_rpm) -qa --qf '$(rpm_knowledge.rpm3_output_format)'";
      package_patch_list_command => "$(redhat_knowledge.call_yum) $(redhat_knowledge.yum_offline_options) check-update $(redhat_knowledge.check_update_postproc)";

      package_list_name_regex    => "$(rpm_knowledge.rpm3_name_regex)";
      package_list_version_regex => "$(rpm_knowledge.rpm3_version_regex)";
      package_list_arch_regex    => "$(rpm_knowledge.rpm3_arch_regex)";

      package_installed_regex => ".*";
      package_name_convention => "$(name)-$(version).$(arch)";

      # 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 => "$(redhat_knowledge.call_yum) $(redhat_knowledge.yum_options) check-update $(redhat_knowledge.check_update_postproc)";
      package_list_update_ifelapsed => $(update_interval);

      package_patch_name_regex    => "$(redhat_knowledge.patch_name_regex)";
      package_patch_version_regex => "$(redhat_knowledge.patch_version_regex)";
      package_patch_arch_regex    => "$(redhat_knowledge.patch_arch_regex)";

      package_add_command    => "$(redhat_knowledge.call_yum) --help >/dev/null 2>&1 ; /bin/true";
      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";
}
