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), "3.19.0");
86      "pkg_release" string => ifelse( isvariable( "def.cfengine_software_pkg_release" ), $(def.cfengine_software_pkg_release), "1");
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      "my_pkg"
499        string => "$(pkg[$(sys.flavor)_$(sys.arch)])",
500        comment => "The package name for the currently executing platform.";
501
502  reports:
503
504    "DEBUG|DEBUG_$(this.bundle)"::
505
506      "My Package: $(my_pkg)";
507}
508
509bundle agent cfengine_master_software_content
510# @brief When cfengine_master_software_content_state_present is defined the software
511# will try be be automatically downloaded.
512{
513  vars:
514      "pkg_name" string => "$(cfengine_software.pkg_name)";
515      "pkg_version" string => "$(cfengine_software.pkg_version)";
516      "pkg_release" string => "$(cfengine_software.pkg_release)";
517      "pkg_arch" string => "$(cfengine_software.pkg_arch)";
518      "package_dir" string => "$(cfengine_software.package_dir)";
519      "pkg_edition" string => "$(cfengine_software.pkg_edition_path)";
520      "base_url" string => "https://cfengine-package-repos.s3.amazonaws.com/$(pkg_edition)";
521
522      # Map platform/directory identifier to upstream package URLs
523      # Better to read in an external explicit data structure?
524
525      "_32bit_arches" slist => { "i386", "i586", "i686" };
526
527      # Redhat/Centos/Oracle 5 and SuSE 11 all use the same package
528      "dir[redhat_5_x86_64]" string => "agent_rpm_x86_64";
529      "dir[centos_5_x86_64]" string => "$(dir[redhat_5_x86_64])";
530      "dir[oracle_5_x86_64]" string => "$(dir[redhat_5_x86_64])";
531      "dir[SuSE_11_x86_64]" string => "$(dir[redhat_5_x86_64])";
532
533      # All 32bit rpms use the same package
534      "_rpm_dists" slist => { "redhat_5", "redhat_6", "redhat_7",
535                              "centos_5", "centos_6", "centos_7",
536                              "SuSE_11", "SuSE_10" };
537
538      "dir[$(_rpm_dists)_$(_32bit_arches)]" string => "agent_rpm_i386";
539
540      # Redhat/Centos/Oracle 6 use the same package
541      "dir[redhat_6_x86_64]" string => "agent_rhel6_x86_64";
542      "dir[centos_6_x86_64]" string => "$(dir[redhat_6_x86_64])";
543      "dir[oracle_6_x86_64]" string => "$(dir[redhat_6_x86_64])";
544
545      # Redhat/Centos/Oracle 7 use the same package
546      "dir[redhat_7_x86_64]" string => "agent_rhel7_x86_64";
547      "dir[centos_7_x86_64]" string => "$(dir[redhat_7_x86_64])";
548      "dir[oracle_7_x86_64]" string => "$(dir[redhat_7_x86_64])";
549
550      # Redhat/Centos/Oracle 8 use the same package
551      "dir[redhat_8_x86_64]" string => "agent_rhel8_x86_64";
552      "dir[centos_8_x86_64]" string => "$(dir[redhat_8_x86_64])";
553      "dir[oracle_8_x86_64]" string => "$(dir[redhat_8_x86_64])";
554
555      # Debian
556      "dir[debian_7_x86_64]" string => "agent_deb_x86_64";
557      "dir[debian_8_x86_64]" string => "agent_debian8_x86_64";
558      "dir[debian_9_x86_64]" string => "agent_debian9_x86_64";
559      "dir[debian_10_x86_64]" string => "agent_debian10_x86_64";
560
561      # Ubuntu
562      "dir[ubuntu_14_x86_64]" string => "agent_ubuntu14_x86_64";
563      "dir[ubuntu_16_x86_64]" string => "agent_ubuntu16_x86_64";
564      "dir[ubuntu_18_x86_64]" string => "agent_ubuntu18_x86_64";
565
566      # All 32bit debs use the same package
567      "_deb_dists" slist => { "debian_4", "debian_5", "debian_6",
568                              "debian_7", "debian_8", "debian_9",
569                              "debian_10", "ubuntu_14", "ubuntu_16",
570                              "ubuntu_18" };
571
572      "dir[$(_deb_dists)_$(_32bit_arches)]" string => "agent_deb_i386";
573
574      "platform_dir" slist => getindices( dir );
575      "download_dir" string => "$(sys.workdir)/master_software_updates";
576
577  files:
578      "$(download_dir)/$(platform_dir)/."
579       create => "true",
580       comment => "We need a place to download each packge we build";
581
582  commands:
583      # Fetch each package that we don't already have
584       "/usr/bin/curl"
585        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)])",
586        if => not( fileexists( "$(download_dir)/$(platform_dir)/$(cfengine_package_names.pkg[$(platform_dir)])" ) );
587
588  reports:
589    DEBUG|DEBUG_cfengine_master_software_content::
590      "curl -s $(base_url)/$(dir[$(platform_dir)])/$(cfengine_package_names.pkg[$(platform_dir)]) --output $(download_dir)/$(platform_dir)/$(cfengine_package_names.pkg[$(platform_dir)])";
591}
592
593bundle edit_line u_backup_script
594# @brief Backup script used by cf-upgrade
595{
596  insert_lines:
597
598    linux::
599
600      "#!/bin/sh
601
602if [ $(const.dollar)1 = \"BACKUP\" ]; then
603 tar cfzS $(const.dollar)2 $(sys.workdir) > /dev/null
604fi
605if [ $(const.dollar)1 = \"RESTORE\" ]; then
606 tar xfz $(const.dollar)2
607fi";
608
609    solarisx86|solaris::
610
611      "#!/bin/sh
612
613if [ $(const.dollar)1 = \"BACKUP\" ]; then
614 tar cf $(const.dollar)2 $(sys.workdir);  gzip $(const.dollar)2
615fi
616if [ $(const.dollar)1 = \"RESTORE\" ]; then
617 gunzip $(const.dollar)2.gz; tar xf $(const.dollar)2
618fi";
619
620}
621bundle edit_line u_install_script
622# @brief Install script used by cf-upgrade
623{
624  insert_lines:
625
626    redhat|suse|sles::
627
628      "#!/bin/sh
629
630/bin/rpm -U $(const.dollar)1";
631
632    debian::
633
634      "#!/bin/sh
635
636/usr/bin/dpkg --force-confdef --force-confnew --install $(const.dollar)1 > /dev/null";
637
638    solarisx86|solaris::
639
640      "#!/bin/sh
641
642pkgname=`pkginfo -d $(const.dollar)1 | awk '{print $(const.dollar)2}'`
643/usr/sbin/pkgrm -n -a $(cfengine_software_version_packages1.admin_file) $pkgname
644/usr/sbin/pkgadd -n -a $(cfengine_software_version_packages1.admin_file) -d $(const.dollar)1 all
645$(sys.workdir)/bin/cf-execd || true
646exit 0";
647
648}
649
650
651bundle edit_line u_admin_file
652# @brief Admin file specification to enable unattended installation
653{
654  insert_lines:
655
656    sunos_5_8::
657
658      "mail=
659instance=unique
660partial=nocheck
661runlevel=nocheck
662idepend=nocheck
663rdepend=nocheck
664space=nocheck
665setuid=nocheck
666conflict=nocheck
667action=nocheck
668basedir=default";
669
670    solaris.!sunos_5_8::
671
672      "mail=
673instance=overwrite
674partial=nocheck
675runlevel=nocheck
676idepend=nocheck
677rdepend=nocheck
678space=nocheck
679setuid=nocheck
680conflict=nocheck
681action=nocheck
682networktimeout=60
683networkretries=3
684authentication=quit
685keystore=/var/sadm/security
686proxy=
687basedir=default";
688
689}
690
691body action u_immediate
692# @brief Ignore promise locks, actuate the promise immediately
693{
694      ifelapsed => "0";
695}
696
697body copy_from u_dsync(from,server)
698# @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.
699# @param from File path to copy from on remote server
700# @param server Remote server to copy file from if executing host is not a policy server
701{
702      # NOTE policy servers cheat and copy directly from the local file system.
703      # This works even if cf-serverd is down and it makes sense if your serving
704      # yourself.
705
706      source      => "$(from)";
707      compare     => "digest";
708      trustkey    => "false";
709      purge       => "true";
710
711    !am_policy_hub::
712
713      servers => { "$(server)" };
714
715    cfengine_internal_encrypt_transfers::
716
717      encrypt => "true";
718}
719
720body classes u_if_repaired(x)
721# @brief Define `x` if promise results in a repair
722# @param x Name of the class to be defined if promise results in repair
723{
724      promise_repaired => { "$(x)" };
725}
726body classes u_if_else(yes,no)
727# @brief Define `yes` if promise results in a repair, `no` if promise is not kept (failed, denied, timeout)
728# @param yes class to define if promise results in repair
729# @param no class to define if promise is not kept (failed, denied, timeout)
730{
731      #      promise_kept     => { "$(yes)" };
732      promise_repaired => { "$(yes)" };
733      repair_failed    => { "$(no)" };
734      repair_denied    => { "$(no)" };
735      repair_timeout   => { "$(no)" };
736}
737
738body common control
739# @brief Common control for standalone self upgrade
740{
741      version => "CFEngine Standalone Self Upgrade 3.19.0";
742
743    (debian|ubuntu)::
744      package_inventory => { $(package_module_knowledge.platform_default) };
745
746      # We only define pacakge_inventory on redhat like systems that have a
747      # python version that works with the package module.
748
749    (redhat|centos)::
750      package_inventory => { $(package_module_knowledge.platform_default) };
751
752    (debian|redhat)::
753      package_module => $(package_module_knowledge.platform_default);
754}
755
756body depth_search u_recurse_basedir(d)
757# @brief Search recursively from (and including) the referenced directory directory to depth `d` excluding common version control paths
758# @param d maximum depth to descend
759{
760      include_basedir => "true";
761      depth => "$(d)";
762      exclude_dirs => { "\.svn", "\.git", "git-core" };
763}
764
765body edit_defaults u_empty_no_backup
766# @brief Do not create backups and ensure we are promising the entire content of
767# the file.
768{
769      empty_file_before_editing => "true";
770      edit_backup => "false";
771}
772
773body file_select plain
774# @brief Select plain, regular files
775{
776      file_types  => { "plain" };
777      file_result => "file_types";
778}
779
780body package_method u_generic(repo)
781# @brief Generic package_method capable of managing packages on multiple platforms.
782# @param repo Local directory to look for packages in
783{
784
785    debian::
786
787        package_changes => "individual";
788        package_list_command => "/usr/bin/dpkg -l";
789
790      # package_list_update_command => "/usr/bin/apt-get update";
791        package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
792
793        package_list_name_regex    => "ii\s+([^\s:]+).*";
794      # package_list_version_regex => "ii\s+[^\s]+\s+([^\s]+).*";
795        package_list_version_regex => "ii\s+[^\s]+\s+(\d+\.\d+((\.|-)\d+)+).*";
796
797        package_installed_regex    => ".*"; # all reported are installed
798
799        package_file_repositories  => { "$(repo)" };
800        package_version_equal_command => "/usr/bin/dpkg --compare-versions '$(v1)' eq '$(v2)'";
801        package_version_less_command => "/usr/bin/dpkg --compare-versions '$(v1)' lt '$(v2)'";
802
803
804    debian.x86_64::
805        package_name_convention    => "$(name)_$(version)_amd64.deb";
806
807    debian.i686::
808        package_name_convention    => "$(name)_$(version)_i386.deb";
809
810    debian::
811        package_add_command        => "/usr/bin/dpkg --force-confdef --force-confnew --install";
812        package_delete_command     => "/usr/bin/dpkg --purge";
813
814    redhat|SuSE|suse|sles::
815
816        package_changes => "individual";
817
818        package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\"";
819
820        package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
821
822        package_list_name_regex    => "[^|]+\|[^|]+\|\s+([^\s|]+).*";
823        package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s|]+).*";
824        package_list_arch_regex    => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*";
825
826        package_installed_regex    => "i.*";
827
828        package_file_repositories  => { "$(repo)" };
829
830        package_name_convention    => "$(name)-$(version).$(arch).rpm";
831
832        package_add_command        => "/bin/rpm -ivh ";
833        package_delete_command     => "/bin/rpm -e --nodeps";
834        package_verify_command     => "/bin/rpm -V";
835        package_noverify_regex     => ".*[^\s].*";
836
837        package_version_less_command => "$(sys.bindir)/rpmvercmp '$(v1)' lt '$(v2)'";
838        package_version_equal_command => "$(sys.bindir)/rpmvercmp '$(v1)' eq '$(v2)'";
839
840    (redhat|SuSE|suse|sles|debian|solarisx86|solaris)::
841        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)";
842
843    redhat.!redhat_4::
844        package_list_update_command => "/usr/bin/yum --quiet check-update";
845    redhat_4::
846        package_list_update_command => "/usr/bin/yum check-update";
847    SuSE|suse|sles::
848        package_list_update_command => "/usr/bin/zypper list-updates";
849
850    windows::
851
852        package_changes => "individual";
853        package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
854        package_file_repositories  => { "$(repo)" };
855
856        package_installed_regex    => ".*";
857
858        package_name_convention    => "$(name)-$(version)-$(arch).msi";
859
860        package_add_command        => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i";
861        package_update_command     => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i";
862        package_delete_command     => "\"$(sys.winsysdir)\msiexec.exe\" /qn /x";
863        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)"';
864        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)"';
865
866    freebsd::
867
868        package_changes => "individual";
869
870        package_list_command => "/usr/sbin/pkg_info";
871
872        package_list_update_command => "/usr/bin/true";
873        package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
874
875        package_list_name_regex    => "^(\S+)-(\d+\.?)+";
876        package_list_version_regex => "^\S+-((\d+\.?)+\_\d)";
877
878        package_file_repositories  => { "$(repo)" };
879
880        package_installed_regex    => ".*";
881
882        package_name_convention    => "$(name)-$(version).tbz";
883        package_delete_convention  => "$(name)-$(version)";
884
885        package_add_command        => "/usr/sbin/pkg_add";
886        package_delete_command     => "/usr/sbin/pkg_delete";
887
888    netbsd::
889
890        package_changes => "individual";
891
892        package_list_command => "/usr/sbin/pkg_info";
893
894        package_list_update_command => "/usr/bin/true";
895        package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
896
897        package_list_name_regex    => "^(\S+)-(\d+\.?)+";
898        package_list_version_regex => "^\S+-((\d+\.?)+\nb\d)";
899
900        package_file_repositories  => { "$(repo)" };
901
902        package_installed_regex    => ".*";
903
904        package_name_convention    => "$(name)-$(version).tgz";
905        package_delete_convention  => "$(name)-$(version)";
906
907        package_add_command        => "/usr/sbin/pkg_add";
908        package_delete_command     => "/usr/sbin/pkg_delete";
909
910    solarisx86|solaris::
911
912        package_changes => "individual";
913        package_list_command => "/usr/bin/pkginfo -l";
914        package_list_update_command => "/usr/bin/true";
915        package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
916
917        package_multiline_start    => "\s*PKGINST:\s+[^\s]+";
918        package_list_name_regex    => "\s*PKGINST:\s+([^\s]+)";
919        package_list_version_regex => "\s*VERSION:\s+([^\s]+)";
920        package_list_arch_regex    => "\s*ARCH:\s+([^\s]+)";
921
922        package_file_repositories  => { "$(repo)" };
923
924        package_installed_regex    => "\s*STATUS:\s*(completely|partially)\s+installed.*";
925        package_name_convention    => "$(name)-$(version)-$(arch).pkg";
926        package_delete_convention  => "$(name)";
927
928      # Cfengine appends path to package and package name below, respectively
929        package_add_command        => "/bin/sh $(repo)/add_scr $(repo)/admin_file";
930        package_delete_command     => "/usr/sbin/pkgrm -n -a $(repo)/admin_file";
931
932    aix::
933
934        package_changes => "individual";
935
936        package_list_update_command => "/usr/bin/true";
937        package_list_update_ifelapsed => "$(u_common_knowledge.list_update_ifelapsed_now)";
938
939        package_list_command       => "/usr/bin/lslpp -lc";
940        package_list_name_regex    => "[^:]+:([^:]+):[^:]+:.*";
941        package_list_version_regex => "[^:]+:[^:]+:([^:]+):.*";
942
943        package_file_repositories  => { "$(repo)" };
944
945        package_installed_regex    => "[^:]+:[^:]+:[^:]+:[^:]*:(COMMITTED|APPLIED):.*";
946
947        package_name_convention    => "$(name)-$(version).bff";
948        package_delete_convention  => "$(name)";
949
950      # Redirecting the output to '/dev/null' below makes sure 'geninstall' has
951      # its stdout open even if the 'cf-agent' process that started it
952      # terminates (e.g. gets killed).
953        package_add_command        => "/usr/bin/rm -f $(repo)/.toc && /usr/sbin/geninstall -IacgXNY -d $(repo) cfengine.cfengine-nova > /dev/null$";
954        package_update_command     => "/usr/bin/rm -f $(repo)/.toc && /usr/sbin/geninstall -IacgXNY -d $(repo) cfengine.cfengine-nova > /dev/null$";
955        package_delete_command     => "/usr/sbin/installp -ug cfengine.cfengine-nova$";
956
957      # Internal version comparison model doesn't work for W.X.Y.Z
958        package_version_less_command => "$(sys.bindir)/rpmvercmp '$(v1)' lt '$(v2)'";
959        package_version_equal_command => "$(sys.bindir)/rpmvercmp '$(v1)' eq '$(v2)'";
960}
961
962body package_module yum
963# @brief Yum package module default settings
964{
965      query_installed_ifelapsed => "10";
966      query_updates_ifelapsed => "30";
967@if minimum_version(3.12.2)
968      interpreter => "$(sys.bindir)/cfengine-selected-python";
969@endif
970}
971
972body package_module apt_get
973# @brief apt_get package module default settings
974{
975      query_installed_ifelapsed => "10";
976      query_updates_ifelapsed => "30";
977@if minimum_version(3.12.2)
978      interpreter => "$(sys.bindir)/cfengine-selected-python";
979@endif
980}
981
982body package_module zypper
983{
984        query_installed_ifelapsed => "0";
985        query_updates_ifelapsed => "30";
986      #default_options =>  {};
987@if minimum_version(3.12.2)
988        interpreter => "$(sys.bindir)/cfengine-selected-python";
989@endif
990}
991
992body package_module msiexec
993# @brief msiexec package module default settings
994{
995      query_installed_ifelapsed => "10";
996      query_updates_ifelapsed => "30";
997@if minimum_version(3.12.2)
998      interpreter => "$(sys.winsysdir)$(const.dirsep)cmd.exe /c ";
999@endif
1000      module_path => "$(sys.workdir)$(const.dirsep)modules$(const.dirsep)packages$(const.dirsep)msiexec.bat";
1001}
1002body perms u_m(p)
1003# @brief Ensure mode is `p`
1004# @param p permissions
1005{
1006      mode  => "$(p)";
1007}
1008
1009body copy_from local_dcp(from)
1010# @brief Copy a local file if the hash on the source file differs.
1011# @param from The path to the source file.
1012#
1013# **Example:**
1014#
1015# ```cf3
1016# bundle agent example
1017# {
1018#   files:
1019#       "/tmp/file.bak"
1020#       copy_from => local_dcp("/tmp/file");
1021# }
1022# ```
1023#
1024# **See Also:** `local_cp()`, `remote_dcp()`
1025{
1026      source      => "$(from)";
1027      compare     => "digest";
1028}
1029