################################################################################
#
# DO NOT EDIT THIS FILE. All policy files prefixed with CFE_ and update_bins.cf
# are maintained by CFEngine and its original state is required for internal
# operations of CFEngine. If the file has been modified CFEngine's upgrades
# may require manual intervention. Contact CFEngine support if additional
# information and/or recommendation is needed.
#
################################################################################
################################################################################
#
# update_bins
#  - CFEngine binary update (native packages)
#
################################################################################

bundle agent cfe_internal_update_bins
# @brief Update cfengine binaries
# TODO Redact this file, not in use. The policy here was migrated into
# standalone self upgrade, nothing includes this policy nor references it's
# bundles
{

  vars:

    enterprise::

      "cf_components"       slist => { "cf-key", "cf-monitord", "cf-promises",
                                       "cf-runagent", "cf-serverd", "cf-hub", },
      comment => "Define cfengine robot agents",
      handle => "cfe_internal_update_bins_vars_cf_components";

      "master_software_location"  string => "/var/cfengine/master_software_updates",
      comment => "The Cfengine binary updates directory on the policy host",
      handle => "cfe_internal_update_bins_vars_master_software_location";

    !hpux::
      "package_dir"
        string => "$(sys.flavour)_$(sys.arch)",
        comment => "The directory within software updates to look for packages";

    hpux::
      "package_dir"
        string => "$(sys.class)_$(sys.arch)",
        comment => "The directory within software updates to look for packages.
                    On HPUX sys.flavor includes versions, so we use sys.class
                    instead.";

    enterprise::

      "local_software_dir"        string => translatepath("$(sys.workdir)/software_updates/$(package_dir)"),
      comment => "Local directory containing binary updates for this host",
      handle => "cfe_internal_update_bins_vars_local_software_dir";

      "local_update_log_dir"      string => translatepath("$(sys.workdir)/software_updates/update_log"),
      comment => "Local directory to store update log for this host",
      handle => "cfe_internal_update_bins_vars_local_update_log_dir";

    !windows.enterprise::

      # backup script for cf-upgrade
      # the script should have 2 conditions, BACKUP and RESTORE
      # BACKUP and RESTORE status is $(const.dollar)1 variable in the script
      # see more details at bundle edit_line u_backup_script

      "backup_script"   string => "/tmp/cf-upgrade_backup.sh";

      # a single compressed backup file for cf-upgrade
      # this backup_file is passed to backup_script as $(const.dollar)2 variable
      # cf-upgrade will extract this file if return signal of upgrade command is not 0

      "backup_file"     string => "/tmp/cfengine-nova-$(sys.cf_version).tar.gz";

      # install script for cf-upgrade
      # each distribution has its own way to upgrade a package
      # see more details at bundle edit_line u_install_script

      "install_script"  string => "/tmp/cf-upgrade_install.sh";

    (solarisx86|solaris).enterprise::

      # to automatically remove or install packages on Solaris
      # admin_file is a must to have to avoid pop-up interaction
      # see more details at bundle edit_line u_admin_file

      "admin_file"      string => "/tmp/cf-upgrade_admin_file";

    (solarisx86|solaris).enterprise::

      "novapkg"                 string => "cfengine-nova",
      comment => "Name convention of Nova package on Solaris",
      handle => "cfe_internal_update_bins_vars_novapkg_solaris",
      if => "nova_edition";

    aix.enterprise::

      "novapkg"                 string => "cfengine-nova",
      comment => "Name convention of Nova package on AIX",
      handle => "cfe_internal_update_bins_vars_novapkg_aix",
      if => "nova_edition";

    !(solarisx86|solaris|aix).enterprise::

      "novapkg"                 string => "cfengine-nova",
      comment => "Name convention of Nova package for all but not Solaris",
      handle => "cfe_internal_update_bins_vars_novapkg_not_solaris_aix",
      if => "nova_edition";

    solaris.!sunos_i86pc.enterprise::

      "pkgarch"                 string => "sparc",
      comment => "Name convention of package arch on Solaris",
      handle => "cfe_internal_update_bins_vars_pkgarch_solaris";

    solarisx86.enterprise::

      "pkgarch"                 string => "i386",
      comment => "Name convention of package arch on Solaris",
      handle => "cfe_internal_update_bins_vars_pkgarch_solarisx86";

    redhat.i686.enterprise::

      "pkgarch"                 string => "i386",
      comment => "Name convention of package arch on 32-bit RHEL",
      handle => "cfe_internal_update_bins_vars_pkgarch_redhat_32b";

    redhat.(x86_64|ppc64).enterprise::

      "pkgarch"                 string => "$(sys.arch)",
      comment => "Name convention of package arch on RHEL x86_64 and ppc64",
      handle => "cfe_internal_update_bins_vars_pkgarch_redhat_x86_64_and_ppc64";

    (freebsd|netbsd|debian|aix).enterprise::

      "pkgarch"                 string => "*",
      comment => "Name convention of package arch on *BSD/Debian",
      handle => "cfe_internal_update_bins_vars_pkgarch_bsd_debian_aix";

    !(solarisx86|solaris|freebsd|netbsd|debian|aix|redhat).enterprise::

      "pkgarch"                 string => "$(sys.arch)",
      comment => "Name convention of package arch for other system except Solaris and *BSD",
      handle => "cfe_internal_update_bins_vars_pkgarch_not_solaris_bsd_debian_aix_redhat_32b";

      #

  classes:

      "have_software_dir" expression => fileexists($(local_software_dir));

      #

  packages:

    !am_policy_hub.linux.enterprise.trigger_upgrade.!bootstrap_mode::

      "$(novapkg)"
      comment => "Update Nova package to a newer version (package is there)",
      handle => "cfe_internal_update_bins_packages_nova_update_linux_pkg_there",
      package_policy => "update",
      package_select => "==",            # picks the newest Nova available
      package_architectures => { "$(pkgarch)" },
      package_version => "$(update_def.current_version)-$(update_def.current_release)",
      package_method => u_generic( "$(local_software_dir)" ),
      if => "nova_edition.have_software_dir",
      classes => u_if_else("bin_update_success", "bin_update_fail");

    !am_policy_hub.(solaris|solarisx86).enterprise.trigger_upgrade.!bootstrap_mode::

      "$(novapkg)"
      comment => "Update Nova package to a newer version (package is there)",
      handle => "cfe_internal_update_bins_packages_nova_update_solaris_pkg_there",
      package_policy => "update",
      package_select => "==",            # picks the newest Nova available
      package_architectures => { "$(pkgarch)" },
      package_version => "$(update_def.current_version)",
      package_method => u_generic( "$(local_software_dir)" ),
      if => "nova_edition.have_software_dir",
      classes => u_if_else("bin_update_success", "bin_update_fail");

    !am_policy_hub.windows.enterprise.trigger_upgrade.!bootstrap_mode::

      "$(novapkg)"
      comment => "Update Nova package to a newer version (package is there)",
      handle => "cfe_internal_update_bins_packages_nova_update_windows_only_pkg_there",
      package_policy => "update",
      package_select => "==",            # picks the newest Nova available
      package_architectures => { "$(pkgarch)" },
      package_version => "$(update_def.current_version)",
      package_method => u_generic( "$(local_software_dir)" ),
      if => "nova_edition.have_software_dir",
      classes => u_if_else("bin_update_success", "bin_update_fail");

    !am_policy_hub.aix.enterprise.trigger_upgrade.!bootstrap_mode::

      "$(novapkg)"
      comment => "Update Nova package to a newer version (package is there)",
      handle => "cfe_internal_update_bins_packages_nova_update_aix_only_pkg_there",
      package_policy => "update",
      package_select => "==",            # picks the newest Nova available
      package_architectures => { "$(pkgarch)" },
      package_version => "$(update_def.current_version).0",
      package_method => u_generic( "$(local_software_dir)" ),
      if => "nova_edition.have_software_dir",
      classes => u_if_else("bin_update_success", "bin_update_fail");

      #

  files:

    enterprise::

      "$(local_update_log_dir)/$(sys.nova_version)_is_running"
      comment => "Create an empty file about a version that is running",
      handle => "cfe_internal_update_bins_files_version_is_running",
      create => "true";

    am_policy_hub.enterprise::

      "$(master_software_location)/cf-upgrade/linux.i386/."
      comment => "Prepare a directory for cf-upgrade",
      handle => "cfe_internal_update_bins_files_linux_i386",
      create => "true";

      "$(master_software_location)/cf-upgrade/linux.x86_64/."
      comment => "Prepare a directory for cf-upgrade",
      handle => "cfe_internal_update_bins_files_linux_x86_64",
      create => "true";

    !am_policy_hub.enterprise.trigger_upgrade::

      "$(admin_file)"
      comment => "Create solaris admin_file to automate remove and install packages",
      handle => "cfe_internal_update_bins_files_solaris_admin_file",
      create => "true",
      edit_defaults => u_empty_no_backup,
      edit_line => u_admin_file,
      perms => u_m("0644"),
      if => "solarisx86|solaris";

      "$(backup_script)"
      comment => "Create a backup script for cf-upgrade",
      handle => "cfe_internal_update_bins_files_backup_script",
      create => "true",
      if => "!windows",
      edit_defaults => u_empty_no_backup,
      edit_line => u_backup_script,
      perms => u_m("0755");

      "$(install_script)"
      comment => "Create an install script for cf-upgrade",
      handle => "cfe_internal_update_bins_files_install_script",
      create => "true",
      if => "!windows",
      edit_defaults => u_empty_no_backup,
      edit_line => u_install_script,
      perms => u_m("0755");

      "$(local_software_dir)/."
        create => "true",
        handle => "cfe_internal_update_bins_files_local_software_dir_presence",
        comment => "Ensure the local software directory exists for new binaries
                    to be downloaded to";

      "$(local_software_dir)/."
      comment => "Copy binary updates from master source on policy server",
      handle => "cfe_internal_update_bins_files_pkg_copy",
      copy_from => u_pcp("$(master_software_location)/$(package_dir)", @(update_def.policy_servers)),
      depth_search => u_recurse("1"),  # Nova updates should be in root dir
      action => u_immediate,
      classes => u_if_repaired("bin_newpkg");

    bin_update_success.enterprise.trigger_upgrade::

      "$(local_update_log_dir)/upgraded_binary_from_$(sys.nova_version)"
      comment => "Create an empty file after successfully upgrade the binary",
      handle => "cfe_internal_update_bins_files_update_from_log",
      create => "true";

  reports:
    DEBUG|DEBUG_cfe_internal_update_bins::
      "DEBUG $(this.bundle): Evaluating binaries for upgrade using internal update mechanism"
        if => "trigger_upgrade";

}

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

bundle edit_line u_admin_file
# @brief Admin file for automating solaris package installs
{
  insert_lines:

    sunos_5_8::

      "mail=
instance=unique
partial=nocheck
runlevel=nocheck
idepend=nocheck
rdepend=nocheck
space=nocheck
setuid=nocheck
conflict=nocheck
action=nocheck
basedir=default";

    solaris.!sunos_5_8::

      "mail=
instance=overwrite
partial=nocheck
runlevel=nocheck
idepend=nocheck
rdepend=nocheck
space=nocheck
setuid=nocheck
conflict=nocheck
action=nocheck
networktimeout=60
networkretries=3
authentication=quit
keystore=/var/sadm/security
proxy=
basedir=default";

}

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

bundle edit_line u_backup_script
# brief Script to execute before package upgrade
{
  insert_lines:

    linux::

      "#!/bin/sh

if [ $(const.dollar)1 = \"BACKUP\" ]; then
 tar cfzS $(const.dollar)2 $(sys.workdir) > /dev/null
fi
if [ $(const.dollar)1 = \"RESTORE\" ]; then
 tar xfz $(const.dollar)2
fi";

    solarisx86|solaris::

      "#!/bin/sh

if [ $(const.dollar)1 = \"BACKUP\" ]; then
 tar cf $(const.dollar)2 $(sys.workdir);  gzip $(const.dollar)2
fi
if [ $(const.dollar)1 = \"RESTORE\" ]; then
 gunzip $(const.dollar)2.gz; tar xf $(const.dollar)2
fi";

}

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

bundle edit_line u_install_script
# brief Script to upgrade package
{
  insert_lines:

    redhat|suse|sles::

      "#!/bin/sh

/bin/rpm -U $(const.dollar)1";

    debian::

      "#!/bin/sh

/usr/bin/dpkg --force-confdef --force-confnew --install $(const.dollar)1 > /dev/null";

    solarisx86|solaris::

      "#!/bin/sh

pkgname=`pkginfo -d $(const.dollar)1 | awk '{print $(const.dollar)2}'`
/usr/sbin/pkgrm -n -a $(cfe_internal_update_bins.admin_file) $pkgname
/usr/sbin/pkgadd -n -a $(cfe_internal_update_bins.admin_file) -d $(const.dollar)1 all
$(sys.workdir)/bin/cf-execd || true
exit 0";

}

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

body edit_defaults u_empty_no_backup
# @brief Empty file before editing and create no backups
{
  empty_file_before_editing => "true";
  edit_backup => "false";
}

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

body copy_from u_pcp(from,server)
# @brief Copy from `from` on `server` using digest comparison
# @param from Path on remote server to copy from
# @param server Remote host to copy from
{
      source      => "$(from)";
      compare     => "digest";
      trustkey    => "false";
      purge       => "true";

    !am_policy_hub::

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

    cfengine_internal_encrypt_transfers::
      encrypt => "true";
}

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

bundle common u_common_knowledge
# @brief standalone common packages knowledge bundle
#
# This common bundle defines general things about platforms.
# @see common_knowledge
{
  vars:
      "list_update_ifelapsed_now" string => "10080";
}

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

body package_method u_generic(repo)
{

    debian::

      package_changes => "individual";
      package_list_command => "/usr/bin/dpkg -l";

      # package_list_update_command => "/usr/bin/apt-get update";
      package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";

      package_list_name_regex    => "ii\s+([^\s:]+).*";
      # package_list_version_regex => "ii\s+[^\s]+\s+([^\s]+).*";
      package_list_version_regex => "ii\s+[^\s]+\s+(\d+\.\d+((\.|-)\d+)+).*";

      package_installed_regex    => ".*"; # all reported are installed

      package_file_repositories  => { "$(repo)" };
      package_version_equal_command => "/usr/bin/dpkg --compare-versions '$(v1)' eq '$(v2)'";
      package_version_less_command => "/usr/bin/dpkg --compare-versions '$(v1)' lt '$(v2)'";


    debian.x86_64::
      package_name_convention    => "$(name)_$(version)_amd64.deb";

    debian.i686::
      package_name_convention    => "$(name)_$(version)_i386.deb";

    debian::
      package_add_command        => "/usr/bin/dpkg --force-confdef --force-confnew --install";
      package_delete_command     => "/usr/bin/dpkg --purge";

    debian::
      package_update_command     => "$(sys.workdir)/bin/cf-upgrade -b $(cfe_internal_update_bins.backup_script) -s $(cfe_internal_update_bins.backup_file) -i $(cfe_internal_update_bins.install_script)";

    redhat|SuSE|suse|sles::

      package_changes => "individual";

      package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\"";

      package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";

      package_list_name_regex    => "[^|]+\|[^|]+\|\s+([^\s|]+).*";
      package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s|]+).*";
      package_list_arch_regex    => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";

      package_installed_regex    => "i.*";

      package_file_repositories  => { "$(repo)" };

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

      package_add_command        => "/bin/rpm -ivh ";
      package_delete_command     => "/bin/rpm -e --nodeps";
      package_verify_command     => "/bin/rpm -V";
      package_noverify_regex     => ".*[^\s].*";

      package_version_less_command => "$(sys.bindir)/rpmvercmp '$(v1)' lt '$(v2)'";
      package_version_equal_command => "$(sys.bindir)/rpmvercmp '$(v1)' eq '$(v2)'";

    (redhat|SuSE|suse|sles)::
      package_update_command     => "$(sys.workdir)/bin/cf-upgrade -b $(cfe_internal_update_bins.backup_script) -s $(cfe_internal_update_bins.backup_file) -i $(cfe_internal_update_bins.install_script)";

    redhat.!redhat_4::
      package_list_update_command => "/usr/bin/yum --quiet check-update";
    redhat_4::
      package_list_update_command => "/usr/bin/yum check-update";
    SuSE|suse|sles::
      package_list_update_command => "/usr/bin/zypper list-updates";

    windows::

      package_changes => "individual";
      package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
      package_file_repositories  => { "$(repo)" };

      package_installed_regex    => ".*";

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

      package_add_command        => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i";
      package_update_command     => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i";
      package_delete_command     => "\"$(sys.winsysdir)\msiexec.exe\" /qn /x";

    freebsd::

      package_changes => "individual";

      package_list_command => "/usr/sbin/pkg_info";

      package_list_update_command => "/usr/bin/true";
      package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";

      package_list_name_regex    => "^(\S+)-(\d+\.?)+";
      package_list_version_regex => "^\S+-((\d+\.?)+\_\d)";

      package_file_repositories  => { "$(repo)" };

      package_installed_regex    => ".*";

      package_name_convention    => "$(name)-$(version).tbz";
      package_delete_convention  => "$(name)-$(version)";

      package_add_command        => "/usr/sbin/pkg_add";
      package_delete_command     => "/usr/sbin/pkg_delete";

    netbsd::

      package_changes => "individual";

      package_list_command => "/usr/sbin/pkg_info";

      package_list_update_command => "/usr/bin/true";
      package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";

      package_list_name_regex    => "^(\S+)-(\d+\.?)+";
      package_list_version_regex => "^\S+-((\d+\.?)+\nb\d)";

      package_file_repositories  => { "$(repo)" };

      package_installed_regex    => ".*";

      package_name_convention    => "$(name)-$(version).tgz";
      package_delete_convention  => "$(name)-$(version)";

      package_add_command        => "/usr/sbin/pkg_add";
      package_delete_command     => "/usr/sbin/pkg_delete";

    solarisx86|solaris::

      package_changes => "individual";
      package_list_command => "/usr/bin/pkginfo -l";
      package_list_update_command => "/usr/bin/true";
      package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";

      package_multiline_start    => "\s*PKGINST:\s+[^\s]+";
      package_list_name_regex    => "\s*PKGINST:\s+([^\s]+)";
      package_list_version_regex => "\s*VERSION:\s+([^\s]+)";
      package_list_arch_regex    => "\s*ARCH:\s+([^\s]+)";

      package_file_repositories  => { "$(repo)" };

      package_installed_regex    => "\s*STATUS:\s*(completely|partially)\s+installed.*";
      package_name_convention    => "$(name)-$(version)-$(arch).pkg";
      package_delete_convention  => "$(name)";

      # Cfengine appends path to package and package name below, respectively
      package_add_command        => "/bin/sh $(repo)/add_scr $(repo)/admin_file";
      package_delete_command     => "/usr/sbin/pkgrm -n -a $(repo)/admin_file";
    (solarisx86|solaris)::
      package_update_command     => "$(sys.workdir)/bin/cf-upgrade -b $(cfe_internal_update_bins.backup_script) -s $(cfe_internal_update_bins.backup_file) -i $(cfe_internal_update_bins.install_script)";

    aix::

      package_changes => "individual";

      package_list_update_command => "/usr/bin/true";
      package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";

      package_list_command       => "/usr/bin/lslpp -lc";
      package_list_name_regex    => "[^:]+:([^:]+):[^:]+:.*";
      package_list_version_regex => "[^:]+:[^:]+:([^:]+):.*";

      package_file_repositories  => { "$(repo)" };

      package_installed_regex    => "[^:]+:[^:]+:[^:]+:[^:]*:(COMMITTED|APPLIED):.*";

      package_name_convention    => "$(name)-$(version).bff";
      package_delete_convention  => "$(name)";

      package_add_command        => "/usr/bin/rm -f $(repo)/.toc && /usr/sbin/geninstall -IqacgXNY -d $(repo) cfengine-nova$";
      package_update_command     => "/usr/bin/rm -f $(repo)/.toc && /usr/sbin/geninstall -IqacgXNY -d $(repo) cfengine-nova$";

      package_delete_command     => "/usr/sbin/installp -ug cfengine-nova$";

}
