#  This file is part of Cfengine 3 - written and maintained by Cfengine 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.

#########################################################################
#
#   software_local.cf - Application Deployment From Directory Repository
#
#   NOTE: Windows needs to support WMI queries about installed msi files
#         in order for Cfengine to detect them. On Windows 2003,
#         go to Control Panel -> Add/Remove Programs -> 
#         Windows Components -> Mgmnt and Monitoring Tools and check
#         WMI Windows Installer Provider.
#
#   NOTE: Naming conventions are important when updating packages.
#         By default, Cfengine expects "name-version-arch.msi" 
#         on Windows, where name is lowercase, and arch is 
#         i686 or x86_64. No spaces should be included in the filename.
#         The Caption and Version fields inside the msi package
#         are important. They must correspond to the file name as 
#         follows: name = lowercase(spacetodash(Caption)), 
#         version = Version. For any msi-file, use InstEd 
#         (www.instedit.com) to check/modify the 
#         Caption and Version fields 
#         (Tables->Property->ProductName/ProductVersion).
#
#         For example, ProductName "CFEngine Nova" with ProductVersion
#         "1.1.2" for 32-bit Windows will correspond to the filename
#         "cfengine-nova-1.1.2-i686.msi".
#
#########################################################################

bundle agent check_software
{
  vars:

      # software to install if not installed
      "include_software" slist => {
				    "7-zip-4.50-$(sys.arch).msi"
      };

      # this software gets updated if it is installed
      "autoupdate_software" slist => { 
				       "7-zip"
      };							 

      # software to uninstall if it is installed
      "exclude_software" slist => {
				    "7-zip-4.65-$(sys.arch).msi"
      };

  methods:
      #  "any" usebundle => add_software( "@(check_software.include_software)", "$(sys.policy_hub)" );
      #  "any" usebundle => update_software( "@(check_software.autoupdate_software)", "$(sys.policy_hub)" );
      #  "any" usebundle => remove_software( "@(check_software.exclude_software)", "$(sys.policy_hub)" );
}

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

bundle agent add_software(pkg_name, srv)
{
  vars:
      # dir to install from locally - can also check multiple directories
      "local_software_dir" string => "C:\Program Files\Cfengine\software\add";
      
  files:

      "$(local_software_dir)"
      copy_from => remote_cp("/var/cfengine/master_software_updates/$(sys.flavour)_$(sys.arch)/add", "$(srv)"),
      depth_search => recurse("1"),
      classes => if_repaired("got_newpkg"),
      comment => "Copy software from remote repository";


  packages:

      # When to check if the package is installed ?
    got_newpkg|any::
      "$(pkg_name)"
      package_policy           => "add",
      package_method           => msi_implicit( "$(local_software_dir)" ),
      classes                  => if_else("add_success", "add_fail" ),
      comment                  => "Install new software, if not already present";

    reports::
    add_fail::
      "Failed to install one or more packages";
}

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

bundle agent update_software(sw_names, srv)
{
  vars:
      # dir to install from locally - can also check multiple directories
      "local_software_dir" string => "C:\Program Files\Cfengine\software\update";
      
  files:

      "$(local_software_dir)"
      copy_from => remote_cp("/var/cfengine/master_software_updates/$(sys.flavour)_$(sys.arch)/update", "$(srv)"),
      depth_search => recurse("1"),
      classes => if_repaired("got_newpkg"),
      comment => "Copy software updates from remote repository";
      
      
  packages:

      # When to check if the package is updated ?
    got_newpkg|any::
      "$(sw_names)"
      package_policy           => "update",
      package_select           => ">=",                 # picks the newest update available
      package_architectures    => { "$(sys.arch)" },    # install 32 or 64 bit package ?
      package_version          => "1.0",                # at least version 1.0
      package_method           => msi_explicit( "$(local_software_dir)" ),
      classes                  => if_else("update_success", "update_fail");

      
    reports::
    update_fail::
      "Failed to update one or more packages";
}

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

bundle agent remove_software(pkg_name, srv)
{
  vars:
      # dir to install from locally - can also check multiple directories
      "local_software_dir" string => "C:\Program Files\Cfengine\software\remove";
      
  files:

      "$(local_software_dir)"
      copy_from => remote_cp("/var/cfengine/master_software_updates/$(sys.flavour)_$(sys.arch)/remove", "$(srv)"),
      depth_search => recurse("1"),
      classes => if_repaired("got_newpkg"),
      comment => "Copy removable software from remote repository";

  packages:
    got_newpkg::
      "$(pkg_name)"
      package_policy           => "delete",
      package_method           => msi_implicit( "$(local_software_dir)" ),
      classes                  => if_else("remove_success", "remove_fail" ),
      comment                  => "Remove software, if present";

    reports::
    remove_fail::
      "Failed to remove one or more packages";
}
