1# This policy is designed to be run with an independent agent.
2
3# WARNING: Including this policy into the inputs of another policy may result in
4# duplicate definition of bundles.
5
6# TODO remove windows_unattended_upgrade.cf when ENT-6823 allows us to use msiexec packages module
7bundle common standalone_self_upgrade_file_control
8{
9  vars:
10    "inputs" slist => { "$(this.promise_dirname)$(const.dirsep)cfe_internal$(const.dirsep)update$(const.dirsep)windows_unattended_upgrade.cf" };
11}
12
13body file control
14{
15  inputs => { @(standalone_self_upgrade_file_control.inputs) };
16}
17bundle agent main
18# @brief This bundle drives the self upgrade. It actuates the appropriate
19# bundles to download binaries to the hub for serving to clients, caching the
20# software to remote clients, and managing the version of cfengine installed on
21# non hubs.
22{
23  classes:
24
25      "policy_server_dat_unstable"
26        expression => isnewerthan( "$(sys.workdir)/policy_server.dat", "$(sys.workdir)/outputs" ),
27        comment => "If $(sys.workdir)/policy_server.dat is newer than the
28                    outputs directory, it can indicate that the current agent
29                    execution is a result of bootstrap. For stability we want to
30                    skip upgrades during bootstrap. The outputs directory should
31                    be newer than the policy_server.dat on the next agent run
32                    and allow upgrade then.";
33
34  reports:
35      "Running $(this.promise_filename)";
36
37  methods:
38
39      "cfengine_software";
40
41    (am_policy_hub|policy_server).!mpf_disable_hub_masterfiles_software_update_seed::
42
43      "Master Software Repository Data"
44        usebundle => cfengine_master_software_content;
45
46    !(am_policy_hub|policy_server|policy_server_dat_unstable)::
47
48      "Local Software Cache"
49        usebundle => cfengine_software_cached_locally;
50
51      "CFEngine Version"
52        usebundle => cfengine_software_version;
53
54}
55
56bundle common package_module_knowledge
57# @brief common package_module_knowledge bundle
58#
59# This common bundle defines which package modules are the defaults on different
60# platforms.
61{
62  vars:
63    debian|ubuntu::
64      "platform_default" string => "apt_get";
65
66    redhat|centos|amazon_linux::
67      "platform_default" string => "yum";
68}
69bundle common u_common_knowledge
70# @brief standalone common packages knowledge bundle
71#
72# This common bundle defines general things about platforms.
73# @see common_knowledge
74{
75  vars:
76      "list_update_ifelapsed_now" string => "10080";
77}
78bundle agent cfengine_software
79# @brief Variables to control the specifics in desired package selection
80{
81  vars:
82
83      # Default desired CFEngine software
84      "pkg_name" string => ifelse( isvariable( "def.cfengine_software_pkg_name" ), $(def.cfengine_software_pkg_name), "cfengine-nova");
85      "pkg_version" string => ifelse( isvariable( "def.cfengine_software_pkg_version" ), $(def.cfengine_software_pkg_version), "@VERSION@");
86      "pkg_release" string => ifelse( isvariable( "def.cfengine_software_pkg_release" ), $(def.cfengine_software_pkg_release), "@RELEASE@");
87      "pkg_arch" string => ifelse( isvariable( "def.cfengine_software_pkg_arch" ), $(def.cfengine_software_pkg_arch), "x86_64");
88      "package_dir" string => ifelse( isvariable( "def.cfengine_software_pkg_dir" ), $(def.cfengine_software_pkg_dir), "$(sys.flavour)_$(sys.arch)");
89      "pkg_edition_path" string => ifelse( isvariable( "def.cfengine_software_pkg_edition_path" ), $(def.cfengine_software_pkg_edition_path), "enterprise/Enterprise-$(pkg_version)/agent");
90
91    community_edition::
92      "pkg_name" string => "cfengine-community";
93      "pkg_edition_path" string => "community_binaries/Community-$(pkg_version)";
94
95    aix::
96      "pkg_name" string => "cfengine.cfengine-nova";
97      "pkg_arch" string => "default";
98
99      # TODO ENT-3187
100    solaris|solarisx86::
101      "pkg_name" string => "CFE.cfengine-nova";
102
103    (debian|ubuntu).64_bit::
104
105      "pkg_arch"
106        string => "amd64",
107        comment => "On debian hosts it's the standard to use 'amd64' instead of
108                   'x86_64' in package architectures.";
109
110    (redhat|centos|suse|sles).32_bit::
111      "pkg_arch"
112        string => "i386",
113        comment => "i686 is the detected architecture, but the package is
114                    compatible from i386 up.";
115
116    hpux::
117
118      "package_dir"
119        string => "$(sys.class)_$(sys.arch)",
120        comment => "The directory within software updates to look for packages.
121                    On HPUX sys.flavor includes versions, so we use sys.class
122                    instead.";
123    any::
124
125      "local_software_dir"
126        string => translatepath( "$(sys.workdir)/software_updates/$(package_dir)" ),
127        comment => "So that we converge on the first pass we set this last as
128                    package_dir may vary across platforms.";
129
130  reports:
131    DEBUG|DEBUG_cfengine_software::
132      "$(this.bundle) pkg_name = $(pkg_name)";
133      "$(this.bundle) pkg_version = $(pkg_version)";
134      "$(this.bundle) pkg_release = $(pkg_release)";
135      "$(this.bundle) pkg_arch = $(pkg_arch)";
136      "$(this.bundle) package_dir = $(package_dir)";
137
138
139  files:
140      "$(sys.statedir)/MPF/."
141        create => "true";
142
143      "$(sys.statedir)/MPF/desired-cfengine-package-version.json"
144        create => "true";
145
146      "$(sys.statedir)/MPF/desired-cfengine-package-version.json" -> { "ENT-3592", "ENT-3937" }
147        edit_line => cfengine_software_version_data;
148
149    windows::
150      "$(sys.bindir)$(const.dirsep)vercmp.ps1"
151        create => "true",
152        template_method => "mustache",
153        edit_template => "$(this.promise_dirname)$(const.dirsep)/templates/vercmp.ps1",
154        template_data => mergedata( '{}' ),
155        comment => "We need to use specialized version comparison logic for unattended self upgrades.";
156
157}
158
159bundle edit_line cfengine_software_version_data
160# @brief Populate data file with the package information
161# The data this bundle writes is used by the update policy to determine if the
162# standalone self upgrade policy should be run or not.
163# TODO Consider replacing with inline_mustache after 3.10.x is EOL
164{
165      delete_lines: ".*";
166      insert_lines: '{
167"name": "$(cfengine_software.pkg_name)",
168"version": "$(cfengine_software.pkg_version)",
169"release": "$(cfengine_software.pkg_release)",
170"arch": "$(cfengine_software.pkg_arch)"
171}';
172}
173
174bundle agent cfengine_software_cached_locally
175# @brief Ensure that the internal local software mirror is up to date
176{
177  reports:
178    inform_mode::
179      "Ensuring local software cache in $(local_software_dir) is up to date";
180
181  vars:
182      "local_software_dir"
183        string => "$(cfengine_software.local_software_dir)";
184
185      "package_dir"
186        string => "$(cfengine_software.package_dir)";
187
188      "master_software_location" -> { "ENT-4953" }
189        string => "master_software_updates",
190        comment => "The Cfengine binary updates directory on the policy server",
191        handle => "cfe_internal_update_bins_vars_master_software_location";
192
193  files:
194      "$(local_software_dir)/."
195        create => "true",
196        comment => "Ensure the local software directory exists for new binaries
197                    to be downloaded to";
198
199      # NOTE This is pegged to the single upstream policy hub, it won't fail
200      # over to a secondary for copying the binarys to update.
201
202      "$(local_software_dir)"
203        comment => "Copy binary updates from master source on policy server",
204        handle => "cfe_internal_update_bins_files_pkg_copy",
205        copy_from => u_dsync( "$(master_software_location)/$(package_dir)", $(sys.policy_hub) ),
206        file_select => plain,
207        depth_search => u_recurse_basedir(inf),
208        action => u_immediate,
209        classes => u_if_repaired("bin_newpkg");
210
211}
212
213
214bundle agent cfengine_software_version
215# @brief Ensure the version of CFEngine installed is correct for supported
216# platforms. Different platforms leverage different implementations for self
217# upgrading.
218{
219  classes:
220      "__supported_platform" -> { "ENT-5045", "ENT-5152", "ENT-4094" }
221        or => {
222                "redhat.!redhat_4",
223                "centos.!centos_4",
224                "debian",
225                "suse|opensuse",
226                "ubuntu",
227                "hpux",
228                "aix",
229                "windows", # ENT-4094
230        };
231
232      # Add "windows" to __new_implementation classes with ENT-6823
233      "__new_implementation"
234        or => { "redhat", "centos", "ubuntu", "debian", "suse", "opensuse" };
235
236  vars:
237      "pkg_name" string => "$(cfengine_software.pkg_name)";
238      "pkg_version" string => "$(cfengine_software.pkg_version)";
239      "pkg_release" string => "$(cfengine_software.pkg_release)";
240      "_cf_version_release" string => ifelse( isvariable( "sys.cf_version_release" ), "$(sys.cf_version_release)", "1" );
241      "pkg_arch" string => "$(cfengine_software.pkg_arch)";
242      "package_dir" string => "$(cfengine_software.package_dir)";
243      "local_software_dir" string => "$(cfengine_software.local_software_dir)";
244
245  methods:
246    __supported_platform.__new_implementation::
247      "Manage CFEngine Version"
248        usebundle => cfengine_software_version_packages2;
249
250    __supported_platform.!__new_implementation::
251      "Manage CFEngine Version"
252        usebundle => cfengine_software_version_packages1;
253
254      # TODO, remove this and cfe_internal/enterprise/windows_unattended_upgrade.cf
255      # when ENT-6823 allows us to use msiexec.bat packages module.
256      "Windows Unattended Upgrade Workaround"
257        usebundle => windows_unattended_upgrade,
258        if => and(
259          "windows",
260          or(
261              not(strcmp("$(cfengine_software.pkg_version)", "$(sys.cf_version)")),
262              not(strcmp("$(cfengine_software.pkg_release)", "$(_cf_version_release)"))
263            )
264        );
265
266  reports:
267      !__supported_platform.inform_mode::
268        "$(this.bundle) $(package_dir) is not supported";
269}
270
271bundle agent cfengine_software_version_packages2
272# @brief Ensure the correct version of software is installed using the new packages promise implementation
273{
274  vars:
275      "pkg_name" string => "$(cfengine_software.pkg_name)";
276      "pkg_version" string => "$(cfengine_software.pkg_version)";
277      "pkg_release" string => "$(cfengine_software.pkg_release)";
278      "pkg_arch" string => "$(cfengine_software.pkg_arch)";
279      "package_dir" string => "$(cfengine_software.package_dir)";
280      "local_software_dir" string => "$(cfengine_software.local_software_dir)";
281
282  packages:
283
284    (redhat|centos)::
285      "$(local_software_dir)/$(cfengine_package_names.my_pkg)"
286      policy => "present",
287      package_module => yum,
288      comment => "Ensure the latest package is installed";
289
290    (debian|ubuntu)::
291      "$(local_software_dir)/$(cfengine_package_names.my_pkg)"
292      policy => "present",
293      package_module => apt_get,
294      comment => "Ensure the latest package is installed";
295
296    (opensuse|suse)::
297      "$(local_software_dir)/$(cfengine_package_names.my_pkg)"
298        policy => "present",
299        package_module => zypper,
300        comment => "Ensure the latest package is installed";
301
302     # TODO, uncomment the following to enable msiexec packages module (ENT-6823)
303#    windows::
304#      "$(local_software_dir)$(const.dirsep)$(cfengine_package_names.my_pkg)"
305#        policy => "present",
306#        package_module => msiexec,
307#        comment => "Ensure the latest package is installed";
308  reports:
309
310    "DEBUG|DEBUG_$(this.bundle)"::
311      "Running $(this.bundle)";
312}
313
314bundle agent cfengine_software_version_packages1
315# @brief Ensure the correct version of software is installed using the legacy self update mechanism
316#@ **Supported Platforms:**
317#@ - RedHat|Centos|Suse (rpm)
318#@ - Debian|Ubuntu (dpkg)
319#@ - solarisx86|solaris (pkgadd)
320#@ - windows (msiexec)
321#@ - aix (installp)
322#@ **Unsupported Platforms:** (but stubbed)
323#@ - freebsd|netbsd (pkg_add)
324{
325  classes:
326
327      "cf_upgrade" expression => "(redhat|suse|sles|debian|solaris|solarisx86).!(am_policy_hub|policy_server)";
328
329  vars:
330
331      # NOTE These logs are not actively used or cleaned up by anything. Their
332      # use will be phased as platforms migrate to the new packages
333      # implementation for self upgrades.
334
335      "local_update_log_dir"
336        string => translatepath("$(sys.workdir)/software_updates/update_log"),
337        comment => "Local directory to store update log for this host.",
338        handle => "cfe_internal_update_bins_vars_local_update_log_dir";
339
340      "local_software_dir" string => "$(cfengine_software.local_software_dir)";
341
342      "desired_version" -> { "ENT-4094" }
343        string => ifelse("linux", "$(cfengine_software.pkg_version)-$(cfengine_software.pkg_release)",
344                         "windows", "$(cfengine_software.pkg_version).$(cfengine_software.pkg_release)", # ENT-4094
345                         "aix", "$(cfengine_software.pkg_version).0",
346                         $(cfengine_software.pkg_version) ),
347        comment => "The version attribute sometimes contains package release
348                    information and sometimes does not. Here we construct the
349                    version used in the package promise for the given
350                    platform.";
351
352    cf_upgrade::
353
354      # We only use cf-upgrade for some platforms, the need for it has been
355      # deprecated by the new packages promise implementation.
356
357      # backup script for cf-upgrade
358      # the script should have 2 conditions, BACKUP and RESTORE
359      # BACKUP and RESTORE status is $(const.dollar)1 variable in the script
360      # see more details at bundle edit_line u_backup_script
361
362      # NOTE cf-upgrade wants to execute from /tmp by default. This is
363      # problematic for systems where /tmp is mounted with no-exec.
364
365      "backup_script"   string => "/tmp/cf-upgrade_backup.sh";
366
367      # a single compressed backup file for cf-upgrade
368      # this backup_file is passed to backup_script as $(const.dollar)2 variable
369      # cf-upgrade will extract this file if return signal of upgrade command is not 0
370
371      "backup_file"     string => "/tmp/cfengine-nova-$(sys.cf_version).tar.gz";
372
373      # install script for cf-upgrade
374      # each distribution has its own way to upgrade a package
375      # see more details at bundle edit_line u_install_script
376
377      "install_script"  string => "/tmp/cf-upgrade_install.sh";
378
379    (solarisx86|solaris).enterprise::
380
381      # to automatically remove or install packages on Solaris
382      # admin_file is a must to have to avoid pop-up interaction
383      # see more details at bundle edit_line u_admin_file
384
385      "admin_file"      string => "/tmp/cf-upgrade_admin_file";
386
387  files:
388
389      # Remote enterprise agents (non policy hubs) that have `trigger_upgrade` defined
390
391    cf_upgrade.enterprise.trigger_upgrade::
392
393      "$(backup_script)"
394      comment => "Create a backup script for cf-upgrade",
395      handle => "cfe_internal_update_bins_files_backup_script",
396      create => "true",
397      if => "!windows",
398      edit_defaults => u_empty_no_backup,
399      edit_line => u_backup_script,
400      perms => u_m("0755");
401
402      "$(install_script)"
403      comment => "Create an install script for cf-upgrade",
404      handle => "cfe_internal_update_bins_files_install_script",
405      create => "true",
406      if => "!windows",
407      edit_defaults => u_empty_no_backup,
408      edit_line => u_install_script,
409      perms => u_m("0755");
410
411      "$(admin_file)"
412      comment => "Create solaris admin_file to automate remove and install packages",
413      handle => "cfe_internal_update_bins_files_solaris_admin_file",
414      create => "true",
415      edit_defaults => u_empty_no_backup,
416      edit_line => u_admin_file,
417      perms => u_m("0644"),
418      if => "solarisx86|solaris";
419
420  packages:
421    # Only non policy hubs running are allowed to self upgrade
422    # We don't upgrade during bootstrap
423
424    !(am_policy_hub|policy_server|bootstrap_mode).enterprise_edition::
425
426      "$(cfengine_software.pkg_name)"
427        comment => "Update Nova package to a newer version",
428        handle => "cfe_internal_update_bins_packages_nova_update",
429        package_policy => "update",
430        package_select => "==",
431        package_architectures => { "$(cfengine_software.pkg_arch)" },
432        package_version => "$(desired_version)",
433        package_method => u_generic( $(cfengine_software.local_software_dir) ),
434        classes => u_if_else("bin_update_success", "bin_update_fail");
435
436  reports:
437
438    "DEBUG|DEBUG_$(this.bundle)"::
439      "Running $(this.bundle)";
440}
441
442bundle common cfengine_package_names
443# @brief Maps platforms to the package naming convention used by the self upgrade policy
444{
445  vars:
446      "pkg_name" string => "$(cfengine_software.pkg_name)";
447      "pkg_version" string => "$(cfengine_software.pkg_version)";
448      "pkg_release" string => "$(cfengine_software.pkg_release)";
449      "pkg_arch" string => "$(cfengine_software.pkg_arch)";
450
451      # Redhat/Centos/Oracle 5, SLES 11 use the same package
452
453      "pkg[redhat_5_x86_64]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release).el5.centos.x86_64.rpm";
454      "pkg[centos_5_x86_64]" string => "$(pkg[redhat_5_x86_64])";
455      "pkg[oracle_5_x86_64]" string => "$(pkg[redhat_5_x86_64])";
456      "pkg[SuSE_11_x86_64]" string => "$(pkg[redhat_5_x86_64])";
457
458      # 32bit RPMs
459      "pkg[$(cfengine_master_software_content._rpm_dists)_$(cfengine_master_software_content._32bit_arches)]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release).el5.centos.i386.rpm";
460
461      # Redhat/Centos/Oracle 6, SLES 12-15 use the same package
462
463      "pkg[redhat_6_x86_64]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release).el6.x86_64.rpm";
464      "pkg[centos_6_x86_64]" string => "$(pkg[redhat_6_x86_64])";
465      "pkg[oracle_6_x86_64]" string => "$(pkg[redhat_6_x86_64])";
466      "pkg[SuSE_12_x86_64]" string => "$(pkg[redhat_6_x86_64])";
467      "pkg[SuSE_15_x86_64]" string => "$(pkg[redhat_6_x86_64])";
468
469      # Redhat/Centos/Oracle 7 use the same package
470      "pkg[redhat_7_x86_64]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release).el7.x86_64.rpm";
471      "pkg[centos_7_x86_64]" string => "$(pkg[redhat_7_x86_64])";
472      "pkg[oracle_7_x86_64]" string => "$(pkg[redhat_7_x86_64])";
473
474      # Redhat/Centos/Oracle 8 use the same package
475      "pkg[redhat_8_x86_64]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release).el8.x86_64.rpm";
476      "pkg[centos_8_x86_64]" string => "$(pkg[redhat_8_x86_64])";
477      "pkg[oracle_8_x86_64]" string => "$(pkg[redhat_8_x86_64])";
478
479      # 64bit Debian
480
481      "pkg[debian_7_x86_64]"  string => "$(pkg_name)_$(pkg_version)-$(pkg_release).debian7_amd64.deb";
482      "pkg[debian_8_x86_64]"  string => "$(pkg_name)_$(pkg_version)-$(pkg_release).debian8_amd64.deb";
483      "pkg[debian_9_x86_64]"  string => "$(pkg_name)_$(pkg_version)-$(pkg_release).debian9_amd64.deb";
484      "pkg[debian_10_x86_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).debian10_amd64.deb";
485
486      # 64bit Ubuntu
487      "pkg[ubuntu_14_x86_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).ubuntu14_amd64.deb";
488      "pkg[ubuntu_16_x86_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).ubuntu16_amd64.deb";
489      "pkg[ubuntu_18_x86_64]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).ubuntu18_amd64.deb";
490
491      # 32bit DEBs
492
493      "pkg[$(cfengine_master_software_content._deb_dists)_$(cfengine_master_software_content._32bit_arches)]" string => "$(pkg_name)_$(pkg_version)-$(pkg_release).debian7_i386.deb";
494
495      # Windows
496      "pkg[windows_x86_64]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release)-x86_64.msi";
497      "pkg[windows_i686]" string => "$(pkg_name)-$(pkg_version)-$(pkg_release)-i686.msi";
498
499      "my_pkg"
500        string => "$(pkg[$(sys.flavor)_$(sys.arch)])",
501        comment => "The package name for the currently executing platform.";
502
503  reports:
504
505    "DEBUG|DEBUG_$(this.bundle)"::
506
507      "My Package: $(my_pkg)";
508}
509
510bundle agent cfengine_master_software_content
511# @brief When cfengine_master_software_content_state_present is defined the software
512# will try be be automatically downloaded.
513{
514  vars:
515      "pkg_name" string => "$(cfengine_software.pkg_name)";
516      "pkg_version" string => "$(cfengine_software.pkg_version)";
517      "pkg_release" string => "$(cfengine_software.pkg_release)";
518      "pkg_arch" string => "$(cfengine_software.pkg_arch)";
519      "package_dir" string => "$(cfengine_software.package_dir)";
520      "pkg_edition" string => "$(cfengine_software.pkg_edition_path)";
521      "base_url" string => "https://cfengine-package-repos.s3.amazonaws.com/$(pkg_edition)";
522
523      # Map platform/directory identifier to upstream package URLs
524      # Better to read in an external explicit data structure?
525
526      "_32bit_arches" slist => { "i386", "i586", "i686" };
527
528      # Redhat/Centos/Oracle 5 and SuSE 11 all use the same package
529      "dir[redhat_5_x86_64]" string => "agent_rpm_x86_64";
530      "dir[centos_5_x86_64]" string => "$(dir[redhat_5_x86_64])";
531      "dir[oracle_5_x86_64]" string => "$(dir[redhat_5_x86_64])";
532      "dir[SuSE_11_x86_64]" string => "$(dir[redhat_5_x86_64])";
533
534      # All 32bit rpms use the same package
535      "_rpm_dists" slist => { "redhat_5", "redhat_6", "redhat_7",
536                              "centos_5", "centos_6", "centos_7",
537                              "SuSE_11", "SuSE_10" };
538
539      "dir[$(_rpm_dists)_$(_32bit_arches)]" string => "agent_rpm_i386";
540
541      # Redhat/Centos/Oracle 6 use the same package
542      "dir[redhat_6_x86_64]" string => "agent_rhel6_x86_64";
543      "dir[centos_6_x86_64]" string => "$(dir[redhat_6_x86_64])";
544      "dir[oracle_6_x86_64]" string => "$(dir[redhat_6_x86_64])";
545
546      # Redhat/Centos/Oracle 7 use the same package
547      "dir[redhat_7_x86_64]" string => "agent_rhel7_x86_64";
548      "dir[centos_7_x86_64]" string => "$(dir[redhat_7_x86_64])";
549      "dir[oracle_7_x86_64]" string => "$(dir[redhat_7_x86_64])";
550
551      # Redhat/Centos/Oracle 8 use the same package
552      "dir[redhat_8_x86_64]" string => "agent_rhel8_x86_64";
553      "dir[centos_8_x86_64]" string => "$(dir[redhat_8_x86_64])";
554      "dir[oracle_8_x86_64]" string => "$(dir[redhat_8_x86_64])";
555
556      # Debian
557      "dir[debian_7_x86_64]" string => "agent_deb_x86_64";
558      "dir[debian_8_x86_64]" string => "agent_debian8_x86_64";
559      "dir[debian_9_x86_64]" string => "agent_debian9_x86_64";
560      "dir[debian_10_x86_64]" string => "agent_debian10_x86_64";
561
562      # Ubuntu
563      "dir[ubuntu_14_x86_64]" string => "agent_ubuntu14_x86_64";
564      "dir[ubuntu_16_x86_64]" string => "agent_ubuntu16_x86_64";
565      "dir[ubuntu_18_x86_64]" string => "agent_ubuntu18_x86_64";
566
567      # All 32bit debs use the same package
568      "_deb_dists" slist => { "debian_4", "debian_5", "debian_6",
569                              "debian_7", "debian_8", "debian_9",
570                              "debian_10", "ubuntu_14", "ubuntu_16",
571                              "ubuntu_18" };
572
573      "dir[$(_deb_dists)_$(_32bit_arches)]" string => "agent_deb_i386";
574
575      # Windows
576      "dir[windows_x86_64]" string => "windows_x86_64";
577      "dir[windows_i686]"   string => "windows_i686";
578
579      "platform_dir" slist => getindices( dir );
580      "download_dir" string => "$(sys.workdir)/master_software_updates";
581
582  files:
583      "$(download_dir)/$(platform_dir)/."
584       create => "true",
585       comment => "We need a place to download each packge we build";
586
587  commands:
588      # Fetch each package that we don't already have
589       "/usr/bin/curl"
590        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)])",
591        if => not( fileexists( "$(download_dir)/$(platform_dir)/$(cfengine_package_names.pkg[$(platform_dir)])" ) );
592
593  reports:
594    DEBUG|DEBUG_cfengine_master_software_content::
595      "curl -s $(base_url)/$(dir[$(platform_dir)])/$(cfengine_package_names.pkg[$(platform_dir)]) --output $(download_dir)/$(platform_dir)/$(cfengine_package_names.pkg[$(platform_dir)])";
596}
597
598bundle edit_line u_backup_script
599# @brief Backup script used by cf-upgrade
600{
601  insert_lines:
602
603    linux::
604
605      "#!/bin/sh
606
607if [ $(const.dollar)1 = \"BACKUP\" ]; then
608 tar cfzS $(const.dollar)2 $(sys.workdir) > /dev/null
609fi
610if [ $(const.dollar)1 = \"RESTORE\" ]; then
611 tar xfz $(const.dollar)2
612fi";
613
614    solarisx86|solaris::
615
616      "#!/bin/sh
617
618if [ $(const.dollar)1 = \"BACKUP\" ]; then
619 tar cf $(const.dollar)2 $(sys.workdir);  gzip $(const.dollar)2
620fi
621if [ $(const.dollar)1 = \"RESTORE\" ]; then
622 gunzip $(const.dollar)2.gz; tar xf $(const.dollar)2
623fi";
624
625}
626bundle edit_line u_install_script
627# @brief Install script used by cf-upgrade
628{
629  insert_lines:
630
631    redhat|suse|sles::
632
633      "#!/bin/sh
634
635/bin/rpm -U $(const.dollar)1";
636
637    debian::
638
639      "#!/bin/sh
640
641/usr/bin/dpkg --force-confdef --force-confnew --install $(const.dollar)1 > /dev/null";
642
643    solarisx86|solaris::
644
645      "#!/bin/sh
646
647pkgname=`pkginfo -d $(const.dollar)1 | awk '{print $(const.dollar)2}'`
648/usr/sbin/pkgrm -n -a $(cfengine_software_version_packages1.admin_file) $pkgname
649/usr/sbin/pkgadd -n -a $(cfengine_software_version_packages1.admin_file) -d $(const.dollar)1 all
650$(sys.workdir)/bin/cf-execd || true
651exit 0";
652
653}
654
655
656bundle edit_line u_admin_file
657# @brief Admin file specification to enable unattended installation
658{
659  insert_lines:
660
661    sunos_5_8::
662
663      "mail=
664instance=unique
665partial=nocheck
666runlevel=nocheck
667idepend=nocheck
668rdepend=nocheck
669space=nocheck
670setuid=nocheck
671conflict=nocheck
672action=nocheck
673basedir=default";
674
675    solaris.!sunos_5_8::
676
677      "mail=
678instance=overwrite
679partial=nocheck
680runlevel=nocheck
681idepend=nocheck
682rdepend=nocheck
683space=nocheck
684setuid=nocheck
685conflict=nocheck
686action=nocheck
687networktimeout=60
688networkretries=3
689authentication=quit
690keystore=/var/sadm/security
691proxy=
692basedir=default";
693
694}
695
696body action u_immediate
697# @brief Ignore promise locks, actuate the promise immediately
698{
699      ifelapsed => "0";
700}
701
702body copy_from u_dsync(from,server)
703# @brief 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.
704# @param from File path to copy from on remote server
705# @param server Remote server to copy file from if executing host is not a policy server
706{
707      # NOTE policy servers cheat and copy directly from the local file system.
708      # This works even if cf-serverd is down and it makes sense if your serving
709      # yourself.
710
711      source      => "$(from)";
712      compare     => "digest";
713      trustkey    => "false";
714      purge       => "true";
715
716    !am_policy_hub::
717
718      servers => { "$(server)" };
719
720    cfengine_internal_encrypt_transfers::
721
722      encrypt => "true";
723}
724
725body classes u_if_repaired(x)
726# @brief Define `x` if promise results in a repair
727# @param x Name of the class to be defined if promise results in repair
728{
729      promise_repaired => { "$(x)" };
730}
731body classes u_if_else(yes,no)
732# @brief Define `yes` if promise results in a repair, `no` if promise is not kept (failed, denied, timeout)
733# @param yes class to define if promise results in repair
734# @param no class to define if promise is not kept (failed, denied, timeout)
735{
736      #      promise_kept     => { "$(yes)" };
737      promise_repaired => { "$(yes)" };
738      repair_failed    => { "$(no)" };
739      repair_denied    => { "$(no)" };
740      repair_timeout   => { "$(no)" };
741}
742
743body common control
744# @brief Common control for standalone self upgrade
745{
746      version => "CFEngine Standalone Self Upgrade @VERSION@";
747
748    (debian|ubuntu)::
749      package_inventory => { $(package_module_knowledge.platform_default) };
750
751      # We only define pacakge_inventory on redhat like systems that have a
752      # python version that works with the package module.
753
754    (redhat|centos)::
755      package_inventory => { $(package_module_knowledge.platform_default) };
756
757    (debian|redhat)::
758      package_module => $(package_module_knowledge.platform_default);
759}
760
761body depth_search u_recurse_basedir(d)
762# @brief Search recursively from (and including) the referenced directory directory to depth `d` excluding common version control paths
763# @param d maximum depth to descend
764{
765      include_basedir => "true";
766      depth => "$(d)";
767      exclude_dirs => { "\.svn", "\.git", "git-core" };
768}
769
770body edit_defaults u_empty_no_backup
771# @brief Do not create backups and ensure we are promising the entire content of
772# the file.
773{
774      empty_file_before_editing => "true";
775      edit_backup => "false";
776}
777
778body file_select plain
779# @brief Select plain, regular files
780{
781      file_types  => { "plain" };
782      file_result => "file_types";
783}
784
785body package_method u_generic(repo)
786# @brief Generic package_method capable of managing packages on multiple platforms.
787# @param repo Local directory to look for packages in
788{
789
790    debian::
791
792        package_changes => "individual";
793        package_list_command => "/usr/bin/dpkg -l";
794
795      # package_list_update_command => "/usr/bin/apt-get update";
796        package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
797
798        package_list_name_regex    => "ii\s+([^\s:]+).*";
799      # package_list_version_regex => "ii\s+[^\s]+\s+([^\s]+).*";
800        package_list_version_regex => "ii\s+[^\s]+\s+(\d+\.\d+((\.|-)\d+)+).*";
801
802        package_installed_regex    => ".*"; # all reported are installed
803
804        package_file_repositories  => { "$(repo)" };
805        package_version_equal_command => "/usr/bin/dpkg --compare-versions '$(v1)' eq '$(v2)'";
806        package_version_less_command => "/usr/bin/dpkg --compare-versions '$(v1)' lt '$(v2)'";
807
808
809    debian.x86_64::
810        package_name_convention    => "$(name)_$(version)_amd64.deb";
811
812    debian.i686::
813        package_name_convention    => "$(name)_$(version)_i386.deb";
814
815    debian::
816        package_add_command        => "/usr/bin/dpkg --force-confdef --force-confnew --install";
817        package_delete_command     => "/usr/bin/dpkg --purge";
818
819    redhat|SuSE|suse|sles::
820
821        package_changes => "individual";
822
823        package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\"";
824
825        package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
826
827        package_list_name_regex    => "[^|]+\|[^|]+\|\s+([^\s|]+).*";
828        package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s|]+).*";
829        package_list_arch_regex    => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
830
831        package_installed_regex    => "i.*";
832
833        package_file_repositories  => { "$(repo)" };
834
835        package_name_convention    => "$(name)-$(version).$(arch).rpm";
836
837        package_add_command        => "/bin/rpm -ivh ";
838        package_delete_command     => "/bin/rpm -e --nodeps";
839        package_verify_command     => "/bin/rpm -V";
840        package_noverify_regex     => ".*[^\s].*";
841
842        package_version_less_command => "$(sys.bindir)/rpmvercmp '$(v1)' lt '$(v2)'";
843        package_version_equal_command => "$(sys.bindir)/rpmvercmp '$(v1)' eq '$(v2)'";
844
845    (redhat|SuSE|suse|sles|debian|solarisx86|solaris)::
846        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)";
847
848    redhat.!redhat_4::
849        package_list_update_command => "/usr/bin/yum --quiet check-update";
850    redhat_4::
851        package_list_update_command => "/usr/bin/yum check-update";
852    SuSE|suse|sles::
853        package_list_update_command => "/usr/bin/zypper list-updates";
854
855    windows::
856
857        package_changes => "individual";
858        package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
859        package_file_repositories  => { "$(repo)" };
860
861        package_installed_regex    => ".*";
862
863        package_name_convention    => "$(name)-$(version)-$(arch).msi";
864
865        package_add_command        => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i";
866        package_update_command     => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i";
867        package_delete_command     => "\"$(sys.winsysdir)\msiexec.exe\" /qn /x";
868        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)"';
869        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)"';
870
871    freebsd::
872
873        package_changes => "individual";
874
875        package_list_command => "/usr/sbin/pkg_info";
876
877        package_list_update_command => "/usr/bin/true";
878        package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
879
880        package_list_name_regex    => "^(\S+)-(\d+\.?)+";
881        package_list_version_regex => "^\S+-((\d+\.?)+\_\d)";
882
883        package_file_repositories  => { "$(repo)" };
884
885        package_installed_regex    => ".*";
886
887        package_name_convention    => "$(name)-$(version).tbz";
888        package_delete_convention  => "$(name)-$(version)";
889
890        package_add_command        => "/usr/sbin/pkg_add";
891        package_delete_command     => "/usr/sbin/pkg_delete";
892
893    netbsd::
894
895        package_changes => "individual";
896
897        package_list_command => "/usr/sbin/pkg_info";
898
899        package_list_update_command => "/usr/bin/true";
900        package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
901
902        package_list_name_regex    => "^(\S+)-(\d+\.?)+";
903        package_list_version_regex => "^\S+-((\d+\.?)+\nb\d)";
904
905        package_file_repositories  => { "$(repo)" };
906
907        package_installed_regex    => ".*";
908
909        package_name_convention    => "$(name)-$(version).tgz";
910        package_delete_convention  => "$(name)-$(version)";
911
912        package_add_command        => "/usr/sbin/pkg_add";
913        package_delete_command     => "/usr/sbin/pkg_delete";
914
915    solarisx86|solaris::
916
917        package_changes => "individual";
918        package_list_command => "/usr/bin/pkginfo -l";
919        package_list_update_command => "/usr/bin/true";
920        package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
921
922        package_multiline_start    => "\s*PKGINST:\s+[^\s]+";
923        package_list_name_regex    => "\s*PKGINST:\s+([^\s]+)";
924        package_list_version_regex => "\s*VERSION:\s+([^\s]+)";
925        package_list_arch_regex    => "\s*ARCH:\s+([^\s]+)";
926
927        package_file_repositories  => { "$(repo)" };
928
929        package_installed_regex    => "\s*STATUS:\s*(completely|partially)\s+installed.*";
930        package_name_convention    => "$(name)-$(version)-$(arch).pkg";
931        package_delete_convention  => "$(name)";
932
933      # Cfengine appends path to package and package name below, respectively
934        package_add_command        => "/bin/sh $(repo)/add_scr $(repo)/admin_file";
935        package_delete_command     => "/usr/sbin/pkgrm -n -a $(repo)/admin_file";
936
937    aix::
938
939        package_changes => "individual";
940
941        package_list_update_command => "/usr/bin/true";
942        package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
943
944        package_list_command       => "/usr/bin/lslpp -lc";
945        package_list_name_regex    => "[^:]+:([^:]+):[^:]+:.*";
946        package_list_version_regex => "[^:]+:[^:]+:([^:]+):.*";
947
948        package_file_repositories  => { "$(repo)" };
949
950        package_installed_regex    => "[^:]+:[^:]+:[^:]+:[^:]*:(COMMITTED|APPLIED):.*";
951
952        package_name_convention    => "$(name)-$(version).bff";
953        package_delete_convention  => "$(name)";
954
955      # Redirecting the output to '/dev/null' below makes sure 'geninstall' has
956      # its stdout open even if the 'cf-agent' process that started it
957      # terminates (e.g. gets killed).
958        package_add_command        => "/usr/bin/rm -f $(repo)/.toc && /usr/sbin/geninstall -IacgXNY -d $(repo) cfengine.cfengine-nova > /dev/null$";
959        package_update_command     => "/usr/bin/rm -f $(repo)/.toc && /usr/sbin/geninstall -IacgXNY -d $(repo) cfengine.cfengine-nova > /dev/null$";
960        package_delete_command     => "/usr/sbin/installp -ug cfengine.cfengine-nova$";
961
962      # Internal version comparison model doesn't work for W.X.Y.Z
963        package_version_less_command => "$(sys.bindir)/rpmvercmp '$(v1)' lt '$(v2)'";
964        package_version_equal_command => "$(sys.bindir)/rpmvercmp '$(v1)' eq '$(v2)'";
965}
966
967body package_module yum
968# @brief Yum package module default settings
969{
970      query_installed_ifelapsed => "10";
971      query_updates_ifelapsed => "30";
972@if minimum_version(3.12.2)
973      interpreter => "$(sys.bindir)/cfengine-selected-python";
974@endif
975}
976
977body package_module apt_get
978# @brief apt_get package module default settings
979{
980      query_installed_ifelapsed => "10";
981      query_updates_ifelapsed => "30";
982@if minimum_version(3.12.2)
983      interpreter => "$(sys.bindir)/cfengine-selected-python";
984@endif
985}
986
987body package_module zypper
988{
989        query_installed_ifelapsed => "0";
990        query_updates_ifelapsed => "30";
991      #default_options =>  {};
992@if minimum_version(3.12.2)
993        interpreter => "$(sys.bindir)/cfengine-selected-python";
994@endif
995}
996
997body package_module msiexec
998# @brief msiexec package module default settings
999{
1000      query_installed_ifelapsed => "10";
1001      query_updates_ifelapsed => "30";
1002@if minimum_version(3.12.2)
1003      interpreter => "$(sys.winsysdir)$(const.dirsep)cmd.exe /c ";
1004@endif
1005      module_path => "$(sys.workdir)$(const.dirsep)modules$(const.dirsep)packages$(const.dirsep)msiexec.bat";
1006}
1007body perms u_m(p)
1008# @brief Ensure mode is `p`
1009# @param p permissions
1010{
1011      mode  => "$(p)";
1012}
1013
1014body copy_from local_dcp(from)
1015# @brief Copy a local file if the hash on the source file differs.
1016# @param from The path to the source file.
1017#
1018# **Example:**
1019#
1020# ```cf3
1021# bundle agent example
1022# {
1023#   files:
1024#       "/tmp/file.bak"
1025#       copy_from => local_dcp("/tmp/file");
1026# }
1027# ```
1028#
1029# **See Also:** `local_cp()`, `remote_dcp()`
1030{
1031      source      => "$(from)";
1032      compare     => "digest";
1033}
1034