1###############################################################################
2#
3#   update.cf - Basic Update Policy
4#
5###############################################################################
6
7body common control
8# @brief Common control attributes for all components
9{
10      bundlesequence => {
11                          "update_def",
12                          "u_cfengine_enterprise",
13                          @(u_cfengine_enterprise.def),
14                          "cfe_internal_dc_workflow",
15                          "cfe_internal_update_policy",
16                          "cfengine_internal_standalone_self_upgrade",
17                          "cfe_internal_update_processes",
18                          @(update_def.bundlesequence_end), # Define control_common_update_bundlesequnce_end via augments
19      };
20
21      version => "update.cf $(update_def.current_version)";
22
23      inputs => {
24                  "cfe_internal/update/lib.cf",
25                  "cfe_internal/update/systemd_units.cf",
26                  @(cfengine_update_controls.update_def_inputs),
27                  "cfe_internal/update/cfe_internal_dc_workflow.cf",
28                  "cfe_internal/update/cfe_internal_update_from_repository.cf",
29                  "cfe_internal/update/update_policy.cf",
30                  "cfe_internal/update/update_processes.cf",
31                  @(update_def.augments_inputs)
32      };
33
34    any::
35        ignore_missing_bundles => "$(update_def.control_common_ignore_missing_bundles)";
36        ignore_missing_inputs => "$(update_def.control_common_ignore_missing_inputs)";
37
38}
39
40#############################################################################
41bundle common cfengine_update_controls
42# @brief Resolve other controls necessary for update
43{
44  vars:
45       "update_def_inputs"
46        slist => {
47                   "controls/update_def.cf",
48                   "controls/update_def_inputs.cf",
49                 };
50
51  reports:
52    DEBUG|DEBUG_cfengine_update_controls::
53      "DEBUG $(this.bundle): update def inputs='$(update_def_inputs)'";
54}
55
56bundle agent cfengine_internal_standalone_self_upgrade
57# @brief Manage desired version state and execution of policy to reach the target version.
58{
59  methods:
60      "cfengine_internal_standalone_self_upgrade_state_data";
61      "cfengine_internal_standalone_self_upgrade_execution";
62}
63bundle agent cfengine_internal_standalone_self_upgrade_state_data
64# @brief Clear stale recorded desired version information from state
65{
66  vars:
67
68      "binary_upgrade_entry"
69        string => "$(this.promise_dirname)/standalone_self_upgrade.cf";
70
71      "desired_pkg_data_path" string =>
72        "$(cfengine_internal_standalone_self_upgrade_execution.desired_pkg_data_path)";
73
74  files:
75
76      # We consider the data stale if it's older than the policy that generated it
77      "$(desired_pkg_data_path)" -> { "ENT-4317" }
78        delete => u_tidy,
79        if => isnewerthan( $(binary_upgrade_entry) , $(desired_pkg_data_path) );
80}
81bundle agent cfengine_internal_standalone_self_upgrade_execution
82# @brief Manage the version of CFEngine that is currently installed. This policy
83# executes a stand alone policy as a sub agent. If systemd is found we assume
84# that it is necessary to escape the current unit via systemd-run.
85#
86# If the running version matches either the desired version information in state
87# or the version supplied from augments, then we skip running the standalone
88# upgrade policy.
89{
90  vars:
91
92      "exec_prefix"
93        string => ifelse( isexecutable("/bin/systemd-run"), "/bin/systemd-run --unit=cfengine-upgrade --scope ", # trailing space in commands important
94                          isexecutable( "/usr/bin/systemd-run" ), "/usr/bin/systemd-run --unit=cfengine-upgrade --scope ",
95                          "");
96
97      "desired_pkg_data_path" -> { "ENT-3592" }
98        string => "$(sys.statedir)/MPF/desired-cfengine-package-version.json";
99
100      "desired_pkg_data" -> { "ENT-3592" }
101        data => readjson( $(desired_pkg_data_path), inf ),
102        if => fileexists( $(desired_pkg_data_path) );
103
104      "local_update_log_dir"
105        string => translatepath("$(sys.workdir)/software_updates/update_log"),
106        comment => "This directory is used for logging the current version of cfengine running.";
107
108  classes:
109      # If we are running the version desired by the self upgrade policy
110      "at_desired_version_by_policy_specification" -> { "ENT-3592" }
111        expression => strcmp( "$(desired_pkg_data[version])", "$(sys.cf_version)"  );
112
113      # If we are running the version explicitly defined by the user
114      "at_desired_version_by_user_specification" -> { "ENT-3592" }
115        expression => strcmp( "$(def.cfengine_software_pkg_version)", "$(sys.cf_version)" );
116
117      "at_desired_version"
118        or => { "at_desired_version_by_user_specification", "at_desired_version_by_policy_specification" };
119
120  files:
121
122    enterprise_edition::
123
124      "$(local_update_log_dir)/$(sys.cf_version)_is_running" -> { "ENT-4352" }
125        comment => "This results in a record of the first time the enterprise
126                    agent of a given version is seen to run on a host.",
127        handle => "cfe_internal_update_bins_files_version_is_running",
128        create => "true";
129
130  commands:
131
132    trigger_upgrade.!at_desired_version::
133
134      '$(exec_prefix)$(sys.cf_agent) --inform --timestamp --file "$(this.promise_dirname)$(const.dirsep)standalone_self_upgrade.cf" --define trigger_upgrade,update_cf_initiated >"$(sys.workdir)$(const.dirsep)outputs/standalone_self_upgrade_$(sys.cdate).log"'
135      handle => "standalone_self_upgrade",
136      contain => in_shell;
137
138  reports:
139
140    trigger_upgrade.(inform_mode|verbose_mode|DEBUG|DEBUG_cfengine_internal_standalone_self_upgrade)::
141      "Skipped self upgrade because we are running the desired version $(sys.cf_version)" -> { "ENT-3592" }
142        if => "at_desired_version";
143
144}
145
146body agent control
147# @brief Agent controls for update
148{
149      ifelapsed => "1";
150      skipidentify => "true";
151}
152
153#############################################################################
154
155body classes u_kept_successful_command
156# @brief Set command to "kept" instead of "repaired" if it returns 0
157{
158      kept_returncodes => { "0" };
159      failed_returncodes => { "1" };
160}
161body contain in_shell
162{
163  useshell => "true";
164}
165