standalone_self_upgrade.cf
$(sys.inputdir)/standalone_self_upgrade.cf
is an independent policy set entry
like promises.cf
and update.cf
. The policy is executed by an independent
agent executed from the update.cf
entry when the class trigger_upgrade
is
defined and the host is not seen to be running the desired version of the agent.
The policy is designed for use with Enterprise packages, but can be customized
for use with community packages.
file bodies
control
Prototype: control
Implementation:
body file control
{
inputs => { @(standalone_self_upgrade_file_control.inputs) };
}
agent bodies
control
Prototype: control
Description: Agent controls for standalone self upgrade
Implementation:
body agent control
{
control_agent_agentfacility_configured::
agentfacility => "$(default:update_def.control_agent_agentfacility)";
}
action bodies
u_immediate
Prototype: u_immediate
Description: Ignore promise locks, actuate the promise immediately
Implementation:
body action u_immediate
{
ifelapsed => "0";
}
copy_from bodies
u_dsync
Prototype: u_dsync(from, server)
Description: Synchronize promiser with from
on server
using digest comparison. If host is a policy hub, then it skips the remote copy, preferring the local file path. For this reason, this body is not compatible with shortcuts defined by cf-serverd.
Arguments:
from
: File path to copy from on remote serverserver
: Remote server to copy file from if executing host is not a policy server
Implementation:
body copy_from u_dsync(from,server)
{
# NOTE policy servers cheat and copy directly from the local file system.
# This works even if cf-serverd is down and it makes sense if your serving
# yourself.
source => "$(from)";
compare => "digest";
trustkey => "false";
purge => "true";
!am_policy_hub::
servers => { "$(server)" };
cfengine_internal_encrypt_transfers::
encrypt => "true";
}
classes bodies
u_if_repaired
Prototype: u_if_repaired(x)
Description: Define x
if promise results in a repair
Arguments:
x
: Name of the class to be defined if promise results in repair
Implementation:
body classes u_if_repaired(x)
{
promise_repaired => { "$(x)" };
}
u_if_else
Prototype: u_if_else(yes, no)
Description: Define yes
if promise results in a repair, no
if promise is not kept (failed, denied, timeout)
Arguments:
yes
: class to define if promise results in repairno
: class to define if promise is not kept (failed, denied, timeout)
Implementation:
body classes u_if_else(yes,no)
{
# promise_kept => { "$(yes)" };
promise_repaired => { "$(yes)" };
repair_failed => { "$(no)" };
repair_denied => { "$(no)" };
repair_timeout => { "$(no)" };
}
common bodies
control
Prototype: control
Description: Common control for standalone self upgrade
Implementation:
body common control
{
version => "CFEngine Standalone Self Upgrade 3.24.2a.b871c892f";
control_common_tls_min_version_defined::
tls_min_version => "$(default:def.control_common_tls_min_version)"; # See also: allowtlsversion in body server control
control_common_tls_ciphers_defined::
tls_ciphers => "$(default:def.control_common_tls_ciphers)"; # See also: allowciphers in body server control
(debian|ubuntu)::
package_inventory => { $(package_module_knowledge.platform_default) };
# We only define pacakge_inventory on redhat like systems that have a
# python version that works with the package module.
(redhat|centos)::
package_inventory => { $(package_module_knowledge.platform_default) };
(debian|redhat)::
package_module => $(package_module_knowledge.platform_default);
}
depth_search bodies
u_recurse_basedir
Prototype: u_recurse_basedir(d)
Description: Search recursively from (and including) the referenced directory directory to depth d
excluding common version control paths
Arguments:
d
: maximum depth to descend
Implementation:
body depth_search u_recurse_basedir(d)
{
include_basedir => "true";
depth => "$(d)";
exclude_dirs => { "\.svn", "\.git", "git-core" };
}
edit_defaults bodies
u_empty_no_backup
Prototype: u_empty_no_backup
Description: Do not create backups and ensure we are promising the entire content of the file.
Implementation:
body edit_defaults u_empty_no_backup
{
empty_file_before_editing => "true";
edit_backup => "false";
}
file_select bodies
plain
Prototype: plain
Description: Select plain, regular files
Implementation:
body file_select plain
{
file_types => { "plain" };
file_result => "file_types";
}
package_method bodies
u_generic
Prototype: u_generic(repo)
Description: Generic package_method capable of managing packages on multiple platforms.
Arguments:
repo
: Local directory to look for packages in
Implementation:
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";
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|debian|solarisx86|solaris)::
package_update_command => "$(sys.workdir)/bin/cf-upgrade -b $(cfengine_software_version_packages1.backup_script) -s $(cfengine_software_version_packages1.backup_file) -i $(cfengine_software_version_packages1.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";
package_version_less_command => '$(sys.winsysdir)$(const.dirsep)WindowsPowerShell$(const.dirsep)v1.0$(const.dirsep)powershell.exe "$(sys.bindir)$(const.dirsep)vercmp.ps1" "$(v1)" "lt" "$(v2)"';
package_version_equal_command => '$(sys.winsysdir)$(const.dirsep)WindowsPowerShell$(const.dirsep)v1.0$(const.dirsep)powershell.exe "$(sys.bindir)$(const.dirsep)vercmp.ps1" "$(v1)" "eq" "$(v2)"';
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";
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)";
# Redirecting the output to '/dev/null' below makes sure 'geninstall' has
# its stdout open even if the 'cf-agent' process that started it
# terminates (e.g. gets killed).
package_add_command => "/usr/bin/rm -f $(repo)/.toc && /usr/sbin/geninstall -IacgXNY -d $(repo) cfengine-nova > /dev/null$";
package_update_command => "/usr/bin/rm -f $(repo)/.toc && /usr/sbin/geninstall -IacgXNY -d $(repo) cfengine-nova > /dev/null$";
package_delete_command => "/usr/sbin/installp -ug cfengine-nova$";
# Internal version comparison model doesn't work for W.X.Y.Z
package_version_less_command => "$(sys.bindir)/rpmvercmp '$(v1)' lt '$(v2)'";
package_version_equal_command => "$(sys.bindir)/rpmvercmp '$(v1)' eq '$(v2)'";
}
package_module bodies
yum
Prototype: yum
Description: Yum package module default settings
Implementation:
body package_module yum
{
query_installed_ifelapsed => "10";
query_updates_ifelapsed => "30";
@if minimum_version(3.12.2)
interpreter => "$(sys.bindir)/cfengine-selected-python";
@endif
}
apt_get
Prototype: apt_get
Description: apt_get package module default settings
Implementation:
body package_module apt_get
{
query_installed_ifelapsed => "10";
query_updates_ifelapsed => "30";
@if minimum_version(3.12.2)
interpreter => "$(sys.bindir)/cfengine-selected-python";
@endif
}
zypper
Prototype: zypper
Implementation:
body package_module zypper
{
query_installed_ifelapsed => "0";
query_updates_ifelapsed => "30";
#default_options => {};
@if minimum_version(3.12.2)
interpreter => "$(sys.bindir)/cfengine-selected-python";
@endif
}
msiexec
Prototype: msiexec
Description: msiexec package module default settings
Implementation:
body package_module msiexec
{
query_installed_ifelapsed => "10";
query_updates_ifelapsed => "30";
@if minimum_version(3.12.2)
interpreter => "$(sys.winsysdir)$(const.dirsep)cmd.exe /c ";
@endif
module_path => "$(sys.workdir)$(const.dirsep)modules$(const.dirsep)packages$(const.dirsep)msiexec.bat";
}
perms bodies
u_m
Prototype: u_m(p)
Description: Ensure mode is p
Arguments:
p
: permissions
Implementation:
body perms u_m(p)
{
mode => "$(p)";
}
copy_from bodies
local_dcp
Prototype: local_dcp(from)
Description: Copy a local file if the hash on the source file differs.
Arguments:
from
: The path to the source file.
Example:
bundle agent example
{
files:
"/tmp/file.bak"
copy_from => local_dcp("/tmp/file");
}
See Also: local_cp()
, remote_dcp()
Implementation:
body copy_from local_dcp(from)
{
source => "$(from)";
compare => "digest";
}
common bodies
standalone_self_upgrade_file_control
Prototype: standalone_self_upgrade_file_control
Implementation:
bundle common standalone_self_upgrade_file_control
{
vars:
"inputs" slist => { "$(this.promise_dirname)$(const.dirsep)cfe_internal$(const.dirsep)update$(const.dirsep)windows_unattended_upgrade.cf" };
}
def_standalone_self_upgrade
Prototype: def_standalone_self_upgrade
Implementation:
bundle common def_standalone_self_upgrade
{
vars:
"control_agent_agentfacility" -> { "ENT-10209" }
string => "",
if => not( isvariable ( "default:def.control_agent_agentfacility" ));
classes:
"control_agent_agentfacility_configured" -> { "ENT-10209" }
expression => regcmp( "LOG_(USER|DAEMON|LOCAL[0-7])",
$(control_agent_agentfacility) ),
comment => concat( "If default:def.control_agent_agentfacility is a",
" valid setting, we want to use it in body agent",
" control for setting agentfacility" );
"control_common_tls_min_version_defined" -> { "ENT-10198" }
expression => isvariable( "default:def.control_common_tls_min_version"),
comment => concat( "If default:def.control_common_tls_min_version is defined then",
" its value will be used for the minimum version in outbound",
" connections. Else the binary default will be used.");
"control_common_tls_ciphers_defined" -> { "ENT-10198" }
expression => isvariable( "default:def.control_common_tls_ciphers"),
comment => concat( "If default:def.control_common_tls_ciphers is defined then",
" its value will be used for the set of tls ciphers allowed",
" for outbound connections. Else the binary default will be used.");
}
agent bundles
main
Prototype: main
Description: This bundle drives the self upgrade. It actuates the appropriate bundles to download binaries to the hub for serving to clients, caching the software to remote clients, and managing the version of cfengine installed on non hubs.
Implementation:
bundle agent main
{
classes:
"policy_server_dat_unstable"
expression => isnewerthan( "$(sys.workdir)/policy_server.dat", "$(sys.workdir)/outputs" ),
comment => "If $(sys.workdir)/policy_server.dat is newer than the
outputs directory, it can indicate that the current agent
execution is a result of bootstrap. For stability we want to
skip upgrades during bootstrap. The outputs directory should
be newer than the policy_server.dat on the next agent run
and allow upgrade then.";
reports:
"Running $(this.promise_filename)";
methods:
"cfengine_software";
(am_policy_hub|policy_server).!mpf_disable_hub_masterfiles_software_update_seed::
"Master Software Repository Data"
usebundle => cfengine_master_software_content;
!(am_policy_hub|policy_server|policy_server_dat_unstable)::
"Local Software Cache"
usebundle => cfengine_software_cached_locally;
"CFEngine Version"
usebundle => cfengine_software_version;
}
common bodies
package_module_knowledge
Prototype: package_module_knowledge
Description: common package_module_knowledge bundle
This common bundle defines which package modules are the defaults on different platforms.
Implementation:
bundle common package_module_knowledge
{
vars:
debian|ubuntu::
"platform_default" string => "apt_get";
redhat|centos|amazon_linux::
"platform_default" string => "yum";
}
u_common_knowledge
Prototype: u_common_knowledge
Description: standalone common packages knowledge bundle
This common bundle defines general things about platforms.
Implementation:
bundle common u_common_knowledge
{
vars:
"list_update_ifelapsed_now" string => "10080";
}
agent bundles
cfengine_software
Prototype: cfengine_software
Description: Variables to control the specifics in desired package selection
Implementation:
bundle agent cfengine_software
{
vars:
any::
# Extract the hub binary version info if it's available. Only expected to
# be available on a client.
"hub_binary_version" -> { "ENT-10664" }
data => data_regextract(
"^(?<major_minor_patch>\d+\.\d+\.\d+)-(?<release>\d+)",
readfile("$(sys.statedir)$(const.dirsep)hub_cf_version.txt" ) ),
if => fileexists( "$(sys.statedir)$(const.dirsep)hub_cf_version.txt" );
# Default desired CFEngine software
"pkg_name" string => ifelse( isvariable( "def.cfengine_software_pkg_name" ), $(def.cfengine_software_pkg_name), "cfengine-nova");
"pkg_version" -> { "ENT-10664" }
string => "$(sys.cf_version_major).$(sys.cf_version_minor).$(sys.cf_version_patch)",
if => "am_policy_hub|policy_server",
comment => "The hub will use its own version to seed client packages.";
"pkg_version" -> { "ENT-10664" }
string => "$(hub_binary_version[major_minor_patch])",
if => isvariable("hub_binary_version[major_minor_patch]"),
comment => "Use the hub binary version if available.";
"pkg_version"
string => "$(def.cfengine_software_pkg_version)",
if => isvariable( "def.cfengine_software_pkg_version" ),
comment => "If the target version is explicitly set, we want to use that.";
"pkg_release" string => "$(sys.cf_version_release)", if => "am_policy_hub|policy_server";
"pkg_release" string => "$(hub_binary_version[release])", if => isvariable("hub_binary_version[release]");
"pkg_release" string => "$(def.cfengine_software_pkg_release)", if => isvariable("def.cfengine_software_pkg_release");
"pkg_arch" string => ifelse( isvariable( "def.cfengine_software_pkg_arch" ), $(def.cfengine_software_pkg_arch), "x86_64");
"package_dir" string => ifelse( isvariable( "def.cfengine_software_pkg_dir" ), $(def.cfengine_software_pkg_dir), "$(sys.flavour)_$(sys.arch)");
"pkg_edition_path" string => ifelse( isvariable( "def.cfengine_software_pkg_edition_path" ), $(def.cfengine_software_pkg_edition_path), "enterprise/Enterprise-$(pkg_version)/agent");
community_edition::
"pkg_name" string => "cfengine-community";
"pkg_edition_path" string => "community_binaries/Community-$(pkg_version)";
aix::
"pkg_name" string => "cfengine-nova";
"pkg_arch" string => "default";
solaris|solarisx86::
"pkg_name" string => "cfengine-nova";
amzn_2::
"package_dir"
string => "amazon_2_$(pkg_arch)";
(debian|ubuntu).64_bit::
"pkg_arch"
string => "amd64",
comment => "On debian hosts it's the standard to use 'amd64' instead of
'x86_64' in package architectures.";
(debian|ubuntu).aarch64::
"pkg_arch"
string => "arm64",
comment => concat( "On debian hosts it's the CFEngine standard to use 'arm64' in",
"the package filename." );
"package_dir"
string => "$(sys.flavor)_arm_64";
(redhat|centos|suse|sles).32_bit::
"pkg_arch"
string => "i386",
comment => "i686 is the detected architecture, but the package is
compatible from i386 up.";
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.";
windows::
"package_dir" -> { "ENT-9010" }
string => "$(sys.class)_$(sys.arch)",
comment => concat( "The directory within software updates to look for ",
"packages. Since one package is built for each",
"supported architecture instead of each platform",
"version architecture we use sys.class and sys.arch.");
any::
"local_software_dir"
string => translatepath( "$(sys.workdir)/software_updates/$(package_dir)" ),
comment => "So that we converge on the first pass we set this last as
package_dir may vary across platforms.";
reports:
DEBUG|DEBUG_cfengine_software::
"$(this.bundle) pkg_name = $(pkg_name)";
"$(this.bundle) pkg_version = $(pkg_version)";
"$(this.bundle) pkg_release = $(pkg_release)";
"$(this.bundle) pkg_arch = $(pkg_arch)";
"$(this.bundle) package_dir = $(package_dir)";
files:
windows::
"$(sys.bindir)$(const.dirsep)vercmp.ps1"
create => "true",
template_method => "mustache",
edit_template => "$(this.promise_dirname)$(const.dirsep)/templates/vercmp.ps1",
template_data => mergedata( '{}' ),
comment => "We need to use specialized version comparison logic for unattended self upgrades.";
}
cfengine_software_cached_locally
Prototype: cfengine_software_cached_locally
Description: Ensure that the internal local software mirror is up to date
Implementation:
bundle agent cfengine_software_cached_locally
{
reports:
inform_mode::
"Ensuring local software cache in $(local_software_dir) is up to date";
vars:
"local_software_dir"
string => "$(cfengine_software.local_software_dir)";
"package_dir"
string => "$(cfengine_software.package_dir)";
"master_software_location" -> { "ENT-4953" }
string => "master_software_updates",
comment => "The Cfengine binary updates directory on the policy server",
handle => "cfe_internal_update_bins_vars_master_software_location";
files:
"$(local_software_dir)/."
create => "true",
comment => "Ensure the local software directory exists for new binaries
to be downloaded to";
# NOTE This is pegged to the single upstream policy hub, it won't fail
# over to a secondary for copying the binarys to update.
"$(local_software_dir)/."
comment => "Copy binary updates from master source on policy server",
handle => "cfe_internal_update_bins_files_pkg_copy",
copy_from => u_dsync( "$(master_software_location)/$(package_dir)", $(sys.policy_hub) ),
file_select => plain,
depth_search => u_recurse_basedir(inf),
action => u_immediate,
classes => u_if_repaired("bin_newpkg");
}
cfengine_software_version
Prototype: cfengine_software_version
Description: Ensure the version of CFEngine installed is correct for supported platforms. Different platforms leverage different implementations for self upgrading.
Implementation:
bundle agent cfengine_software_version
{
classes:
"__supported_platform" -> { "ENT-5045", "ENT-5152", "ENT-4094", "ENT-8247" }
or => {
"amazon_linux",
"redhat.!redhat_4",
"centos.!centos_4",
"debian",
"suse|opensuse",
"ubuntu",
"hpux",
"aix",
"windows", # ENT-4094
};
# Add "windows" to __new_implementation classes with ENT-6823
"__new_implementation"
or => { "amazon_linux", "redhat", "centos", "ubuntu", "debian", "suse", "opensuse" };
vars:
"pkg_name" string => "$(cfengine_software.pkg_name)";
"pkg_version" string => "$(cfengine_software.pkg_version)";
"pkg_release" string => "$(cfengine_software.pkg_release)";
"_cf_version_release" string => ifelse( isvariable( "sys.cf_version_release" ), "$(sys.cf_version_release)", "1" );
"pkg_arch" string => "$(cfengine_software.pkg_arch)";
"package_dir" string => "$(cfengine_software.package_dir)";
"local_software_dir" string => "$(cfengine_software.local_software_dir)";
methods:
__supported_platform.__new_implementation::
"Manage CFEngine Version"
usebundle => cfengine_software_version_packages2;
__supported_platform.!__new_implementation::
"Manage CFEngine Version"
usebundle => cfengine_software_version_packages1;
# TODO, remove this and cfe_internal/enterprise/windows_unattended_upgrade.cf
# when ENT-6823 allows us to use msiexec.bat packages module.
"Windows Unattended Upgrade Workaround"
usebundle => windows_unattended_upgrade,
if => and(
"windows",
or(
not(strcmp("$(cfengine_software.pkg_version)", "$(sys.cf_version)")),
not(strcmp("$(cfengine_software.pkg_release)", "$(_cf_version_release)"))
)
);
reports:
!__supported_platform.inform_mode::
"$(this.bundle) $(package_dir) is not supported";
}
cfengine_software_version_packages2
Prototype: cfengine_software_version_packages2
Description: Ensure the correct version of software is installed using the new packages promise implementation
Implementation:
bundle agent cfengine_software_version_packages2
{
vars:
"pkg_name" string => "$(cfengine_software.pkg_name)";
"pkg_version" string => "$(cfengine_software.pkg_version)";
"pkg_release" string => "$(cfengine_software.pkg_release)";
"pkg_arch" string => "$(cfengine_software.pkg_arch)";
"package_dir" string => "$(cfengine_software.package_dir)";
"local_software_dir" string => "$(cfengine_software.local_software_dir)";
packages:
(amazon_linux|redhat|centos)::
"$(local_software_dir)/$(cfengine_package_names.my_pkg)"
policy => "present",
package_module => yum,
comment => "Ensure the latest package is installed";
(debian|ubuntu)::
"$(local_software_dir)/$(cfengine_package_names.my_pkg)"
policy => "present",
package_module => apt_get,
comment => "Ensure the latest package is installed";
(opensuse|suse)::
"$(local_software_dir)/$(cfengine_package_names.my_pkg)"
policy => "present",
package_module => zypper,
comment => "Ensure the latest package is installed";
# TODO, uncomment the following to enable msiexec packages module (ENT-6823)
# windows::
# "$(local_software_dir)$(const.dirsep)$(cfengine_package_names.my_pkg)"
# policy => "present",
# package_module => msiexec,
# comment => "Ensure the latest package is installed";
reports:
"DEBUG|DEBUG_$(this.bundle)"::
"Running $(this.bundle)";
}
cfengine_software_version_packages1
Prototype: cfengine_software_version_packages1
Description: Ensure the correct version of software is installed using the legacy self update mechanism
Implementation:
bundle agent cfengine_software_version_packages1
{
classes:
"cf_upgrade" expression => "(redhat|suse|sles|debian|solaris|solarisx86).!(am_policy_hub|policy_server)";
vars:
# NOTE These logs are not actively used or cleaned up by anything. Their
# use will be phased as platforms migrate to the new packages
# implementation for self upgrades.
"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";
"local_software_dir" string => "$(cfengine_software.local_software_dir)";
"desired_version" -> { "ENT-4094" }
string => ifelse("linux", "$(cfengine_software.pkg_version)-$(cfengine_software.pkg_release)",
"windows", "$(cfengine_software.pkg_version).$(cfengine_software.pkg_release)", # ENT-4094
"aix", "$(cfengine_software.pkg_version).0",
$(cfengine_software.pkg_version) ),
comment => "The version attribute sometimes contains package release
information and sometimes does not. Here we construct the
version used in the package promise for the given
platform.";
cf_upgrade::
# We only use cf-upgrade for some platforms, the need for it has been
# deprecated by the new packages promise implementation.
# 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
# NOTE cf-upgrade wants to execute from /tmp by default. This is
# problematic for systems where /tmp is mounted with no-exec.
"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";
files:
# Remote enterprise agents (non policy hubs) that have `trigger_upgrade` defined
cf_upgrade.enterprise.trigger_upgrade::
"$(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");
"$(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";
packages:
# Only non policy hubs running are allowed to self upgrade
# We don't upgrade during bootstrap
!(am_policy_hub|policy_server|bootstrap_mode).enterprise_edition::
"$(cfengine_software.pkg_name)"
comment => "Update Nova package to a newer version",
handle => "cfe_internal_update_bins_packages_nova_update",
package_policy => "update",
package_select => "==",
package_architectures => { "$(cfengine_software.pkg_arch)" },
package_version => "$(desired_version)",
package_method => u_generic( $(cfengine_software.local_software_dir) ),
classes => u_if_else("bin_update_success", "bin_update_fail");
reports:
"DEBUG|DEBUG_$(this.bundle)"::
"Running $(this.bundle)";
}
common bodies
cfengine_package_names
Prototype: cfengine_package_names
Description: Maps platforms to the package naming convention used by the self upgrade policy
Implementation:
bundle common cfengine_package_names
{
vars:
"pkg_name" string => "$(cfengine_software.pkg_name)";
"pkg_version" string => "$(cfengine_software.pkg_version)";
"pkg_release" string => "$(cfengine_software.pkg_release)";
"pkg_arch" string => "$(cfengine_software.pkg_arch)";
# Redhat/Centos/Oracle 5, SuSE 11 use the same package
"pkg[redhat_5_x86_64]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release).el5.centos.x86_64.rpm";
"pkg[centos_5_x86_64]" string => "$(pkg[redhat_5_x86_64])";
"pkg[oracle_5_x86_64]" string => "$(pkg[redhat_5_x86_64])";
"pkg[SuSE_11_x86_64]" string => "$(pkg[redhat_5_x86_64])";
# 32bit RPMs
"pkg[$(cfengine_master_software_content._rpm_dists)_$(cfengine_master_software_content._32bit_arches)]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release).el5.centos.i386.rpm";
# Redhat/Centos/Oracle 6, SuSE 12-15, Opensuse Leap 15 use the same package
"pkg[redhat_6_x86_64]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release).el6.x86_64.rpm";
"pkg[centos_6_x86_64]" string => "$(pkg[redhat_6_x86_64])";
"pkg[oracle_6_x86_64]" string => "$(pkg[redhat_6_x86_64])";
"pkg[SuSE_12_x86_64]" string => "$(pkg[redhat_6_x86_64])";
"pkg[SuSE_15_x86_64]" string => "$(pkg[redhat_6_x86_64])";
"pkg[opensuse_leap_15_x86_64]" string => "$(pkg[redhat_6_x86_64])";
# Redhat/Centos/Oracle/Rocky 7/Amazon 2 use the same package
"pkg[redhat_7_x86_64]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release).el7.x86_64.rpm";
"pkg[centos_7_x86_64]" string => "$(pkg[redhat_7_x86_64])";
"pkg[oracle_7_x86_64]" string => "$(pkg[redhat_7_x86_64])";
"pkg[rocky_7_x86_64]" string => "$(pkg[redhat_7_x86_64])";
"pkg[amazon_2_x86_64]" string => "$(pkg[redhat_7_x86_64])";
# Redhat/Centos/Oracle/Rocky 8 use the same package
"pkg[redhat_8_x86_64]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release).el8.x86_64.rpm";
"pkg[centos_8_x86_64]" string => "$(pkg[redhat_8_x86_64])";
"pkg[oracle_8_x86_64]" string => "$(pkg[redhat_8_x86_64])";
"pkg[rocky_8_x86_64]" string => "$(pkg[redhat_8_x86_64])";
# Redhat/Centos/Oracle/Rocky 8 use the same package
"pkg[redhat_9_x86_64]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release).el9.x86_64.rpm";
"pkg[centos_9_x86_64]" string => "$(pkg[redhat_9_x86_64])";
"pkg[oracle_9_x86_64]" string => "$(pkg[redhat_9_x86_64])";
"pkg[rocky_9_x86_64]" string => "$(pkg[redhat_9_x86_64])";
# 64bit Debian
"pkg[debian_7_x86_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).debian7_amd64.deb";
"pkg[debian_8_x86_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).debian8_amd64.deb";
"pkg[debian_9_x86_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).debian9_amd64.deb";
"pkg[debian_10_x86_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).debian10_amd64.deb";
"pkg[debian_11_x86_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).debian11_amd64.deb";
# 64bit Ubuntu
"pkg[ubuntu_14_x86_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).ubuntu14_amd64.deb";
"pkg[ubuntu_16_x86_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).ubuntu16_amd64.deb";
"pkg[ubuntu_18_x86_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).ubuntu18_amd64.deb";
"pkg[ubuntu_20_x86_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).ubuntu20_amd64.deb";
"pkg[ubuntu_22_x86_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).ubuntu22_amd64.deb";
# aarch64 Ubuntu
"pkg[ubuntu_22_arm_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).ubuntu22_arm64.deb";
# aarch64 Debian
"pkg[debian_11_arm_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).debian11_arm64.deb";
# 32bit DEBs
"pkg[$(cfengine_master_software_content._deb_dists)_$(cfengine_master_software_content._32bit_arches)]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).debian7_i386.deb";
# Windows
"pkg[windows_x86_64]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release)-x86_64.msi";
"pkg[windows_i686]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release)-i686.msi";
"my_pkg"
string => "$(pkg[$(cfengine_software.package_dir)])",
comment => "The package name for the currently executing platform.";
reports:
"DEBUG|DEBUG_$(this.bundle)"::
"My Package: $(my_pkg)";
}
agent bundles
cfengine_master_software_content
Prototype: cfengine_master_software_content
Description: When cfengine_master_software_content_state_present is defined the software will try be be automatically downloaded.
Implementation:
bundle agent cfengine_master_software_content
{
vars:
"pkg_name" string => "$(cfengine_software.pkg_name)";
"pkg_version" string => "$(cfengine_software.pkg_version)";
"pkg_release" string => "$(cfengine_software.pkg_release)";
"pkg_arch" string => "$(cfengine_software.pkg_arch)";
"package_dir" string => "$(cfengine_software.package_dir)";
"pkg_edition" string => "$(cfengine_software.pkg_edition_path)";
"base_url" string => "https://cfengine-package-repos.s3.amazonaws.com/$(pkg_edition)";
# Map platform/directory identifier to upstream package URLs
# Better to read in an external explicit data structure?
"_32bit_arches" slist => { "i386", "i586", "i686" };
# Redhat/Centos/Oracle 5 and SuSE 11 all use the same package
"dir[redhat_5_x86_64]" string => "agent_rpm_x86_64";
"dir[centos_5_x86_64]" string => "$(dir[redhat_5_x86_64])";
"dir[oracle_5_x86_64]" string => "$(dir[redhat_5_x86_64])";
"dir[SuSE_11_x86_64]" string => "$(dir[redhat_5_x86_64])";
"pkg[SuSE_12_x86_64]" string => "$(pkg[redhat_6_x86_64])";
"pkg[SuSE_15_x86_64]" string => "$(pkg[redhat_6_x86_64])";
"pkg[opensuse_leap_15_x86_64]" string => "$(pkg[redhat_6_x86_64])";
# All 32bit rpms use the same package
"_rpm_dists" slist => { "redhat_5", "redhat_6", "redhat_7",
"centos_5", "centos_6", "centos_7",
"SuSE_11", "SuSE_10" };
"dir[$(_rpm_dists)_$(_32bit_arches)]" string => "agent_rpm_i386";
# Redhat/Centos/Oracle 6 use the same package
"dir[redhat_6_x86_64]" string => "agent_rhel6_x86_64";
"dir[centos_6_x86_64]" string => "$(dir[redhat_6_x86_64])";
"dir[oracle_6_x86_64]" string => "$(dir[redhat_6_x86_64])";
# Redhat/Centos/Oracle/Rocky 7/Amazon 2 use the same package
"dir[redhat_7_x86_64]" string => "agent_rhel7_x86_64";
"dir[centos_7_x86_64]" string => "$(dir[redhat_7_x86_64])";
"dir[oracle_7_x86_64]" string => "$(dir[redhat_7_x86_64])";
"dir[rocky_7_x86_64]" string => "$(dir[redhat_7_x86_64])";
"dir[amazon_2_x86_64]" string => "$(dir[redhat_7_x86_64])";
# Redhat/Centos/Oracle/Rocky 8 use the same package
"dir[redhat_8_x86_64]" string => "agent_rhel8_x86_64";
"dir[centos_8_x86_64]" string => "$(dir[redhat_8_x86_64])";
"dir[oracle_8_x86_64]" string => "$(dir[redhat_8_x86_64])";
"dir[rocky_8_x86_64]" string => "$(dir[redhat_8_x86_64])";
# Redhat/Centos/Oracle/Rocky 9 use the same package
"dir[redhat_9_x86_64]" string => "agent_rhel9_x86_64";
"dir[centos_9_x86_64]" string => "$(dir[redhat_9_x86_64])";
"dir[oracle_9_x86_64]" string => "$(dir[redhat_9_x86_64])";
"dir[rocky_9_x86_64]" string => "$(dir[redhat_9_x86_64])";
# Debian
"dir[debian_7_x86_64]" string => "agent_deb_x86_64";
"dir[debian_8_x86_64]" string => "agent_debian8_x86_64";
"dir[debian_9_x86_64]" string => "agent_debian9_x86_64";
"dir[debian_10_x86_64]" string => "agent_debian10_x86_64";
"dir[debian_11_x86_64]" string => "agent_debian11_x86_64";
"dir[debian_11_arm_64]" string => "agent_debian11_arm_64";
# Ubuntu
"dir[ubuntu_14_x86_64]" string => "agent_ubuntu14_x86_64";
"dir[ubuntu_16_x86_64]" string => "agent_ubuntu16_x86_64";
"dir[ubuntu_18_x86_64]" string => "agent_ubuntu18_x86_64";
"dir[ubuntu_20_x86_64]" string => "agent_ubuntu20_x86_64";
"dir[ubuntu_22_x86_64]" string => "agent_ubuntu22_x86_64";
"dir[ubuntu_22_arm_64]" string => "agent_ubuntu22_arm_64";
# All 32bit debs use the same package
"_deb_dists" slist => { "debian_4", "debian_5", "debian_6",
"debian_7", "debian_8", "debian_9",
"debian_10", "ubuntu_14", "ubuntu_16",
"ubuntu_18" };
"dir[$(_deb_dists)_$(_32bit_arches)]" string => "agent_deb_i386";
# Windows
"dir[windows_x86_64]" string => "windows_x86_64";
"dir[windows_i686]" string => "windows_i686";
"platform_dir" slist => getindices( dir );
"download_dir" string => "$(sys.workdir)/master_software_updates";
files:
"$(download_dir)/$(platform_dir)/."
create => "true",
comment => "We need a place to download each packge we build";
"$(download_dir)/$(cfengine_software.pkg_version)-downloaded.txt"
content => join( "\n", classesmatching( "binary_downloaded_.*" ) ),
if => isgreaterthan( length(classesmatching( "binary_downloaded_.*" )),
0 ),
comment => concat( "We place a marker of the files downloaded so that",
" the hub can skip the self upgrade policy after",
" download.");
commands:
# Fetch each package that we don't already have
"/usr/bin/curl"
args => "-s $(base_url)/$(dir[$(platform_dir)])/$(cfengine_package_names.pkg[$(platform_dir)]) --output /var/cfengine/master_software_updates/$(platform_dir)/$(cfengine_package_names.pkg[$(platform_dir)])",
if => not( fileexists( "$(download_dir)/$(platform_dir)/$(cfengine_package_names.pkg[$(platform_dir)])" ) ),
classes => u_if_else("binary_downloaded_$(platform_dir)","binary_not_downloaded");
reports:
DEBUG|DEBUG_cfengine_master_software_content::
"curl -s $(base_url)/$(dir[$(platform_dir)])/$(cfengine_package_names.pkg[$(platform_dir)]) --output $(download_dir)/$(platform_dir)/$(cfengine_package_names.pkg[$(platform_dir)])";
}
edit_line bundles
u_backup_script
Prototype: u_backup_script
Description: Backup script used by cf-upgrade
Implementation:
bundle edit_line u_backup_script
{
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";
}
u_install_script
Prototype: u_install_script
Description: Install script used by cf-upgrade
Implementation:
bundle edit_line u_install_script
{
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 $(cfengine_software_version_packages1.admin_file) $pkgname
/usr/sbin/pkgadd -n -a $(cfengine_software_version_packages1.admin_file) -d $(const.dollar)1 all
$(sys.workdir)/bin/cf-execd || true
exit 0";
}
u_admin_file
Prototype: u_admin_file
Description: Admin file specification to enable unattended installation
Implementation:
bundle edit_line u_admin_file
{
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";
}