update.cf

Table of Contents

$(sys.inputdir)/update.cf is responsible for updating policy from the hub as well as ensuring various core cfenigne components are running.

common bodies

cfengine_update_controls

Prototype: cfengine_update_controls

Description: Resolve other controls necessary for update

Implementation:

bundle common cfengine_update_controls
{
  vars:
       "update_def_inputs"
        slist => {
                   "controls/update_def.cf",
                   "controls/update_def_inputs.cf",
                 };

  reports:
    DEBUG|DEBUG_cfengine_update_controls::
      "DEBUG $(this.bundle): update def inputs='$(update_def_inputs)'";
}

agent bundles

cfengine_internal_standalone_self_upgrade

Prototype: cfengine_internal_standalone_self_upgrade

Description: Manage desired version state and execution of policy to reach the target version.

Implementation:

bundle agent cfengine_internal_standalone_self_upgrade
{
  methods:
      "cfengine_internal_standalone_self_upgrade_state_data";
      "cfengine_internal_standalone_self_upgrade_execution";
}

cfengine_internal_standalone_self_upgrade_state_data

Prototype: cfengine_internal_standalone_self_upgrade_state_data

Description: Clear stale recorded desired version information from state

Implementation:

bundle agent cfengine_internal_standalone_self_upgrade_state_data
{
  vars:

      "binary_upgrade_entry"
        string => "$(this.promise_dirname)/standalone_self_upgrade.cf";

      "desired_pkg_data_path" string =>
        "$(cfengine_internal_standalone_self_upgrade_execution.desired_pkg_data_path)";

  files:

      # We consider the data stale if it's older than the policy that generated it
      "$(desired_pkg_data_path)" -> { "ENT-4317" }
        delete => u_tidy,
        if => isnewerthan( $(binary_upgrade_entry) , $(desired_pkg_data_path) );
}

cfengine_internal_standalone_self_upgrade_execution

Prototype: cfengine_internal_standalone_self_upgrade_execution

Description: Manage the version of CFEngine that is currently installed. This policy executes a stand alone policy as a sub agent. If systemd is found we assume that it is necessary to escape the current unit via systemd-run.

If the running version matches either the desired version information in state or the version supplied from augments, then we skip running the standalone upgrade policy.

Implementation:

bundle agent cfengine_internal_standalone_self_upgrade_execution
{
  vars:

      "exec_prefix"
        string => ifelse( isexecutable("/bin/systemd-run"), "/bin/systemd-run --unit=cfengine-upgrade --scope ", # trailing space in commands important
                          isexecutable( "/usr/bin/systemd-run" ), "/usr/bin/systemd-run --unit=cfengine-upgrade --scope ",
                          "");

      "desired_pkg_data_path" -> { "ENT-3592" }
        string => "$(sys.statedir)/MPF/desired-cfengine-package-version.json";

      "desired_pkg_data" -> { "ENT-3592" }
        data => readjson( $(desired_pkg_data_path), inf ),
        if => fileexists( $(desired_pkg_data_path) );

      "local_update_log_dir"
        string => translatepath("$(sys.workdir)/software_updates/update_log"),
        comment => "This directory is used for logging the current version of cfengine running.";

  classes:
      # If we are running the version desired by the self upgrade policy
      "at_desired_version_by_policy_specification" -> { "ENT-3592" }
        expression => strcmp( "$(desired_pkg_data[version])", "$(sys.cf_version)"  );

      # If we are running the version explicitly defined by the user
      "at_desired_version_by_user_specification" -> { "ENT-3592" }
        expression => strcmp( "$(def.cfengine_software_pkg_version)", "$(sys.cf_version)" );

      "at_desired_version"
        or => { "at_desired_version_by_user_specification", "at_desired_version_by_policy_specification" };

  files:

    enterprise_edition::

      "$(local_update_log_dir)/$(sys.cf_version)_is_running" -> { "ENT-4352" }
        comment => "This results in a record of the first time the enterprise
                    agent of a given version is seen to run on a host.",
        handle => "cfe_internal_update_bins_files_version_is_running",
        create => "true";

  commands:

    trigger_upgrade.!at_desired_version::

      '$(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"'
      handle => "standalone_self_upgrade",
      contain => in_shell;

  reports:

    trigger_upgrade.(inform_mode|verbose_mode|DEBUG|DEBUG_cfengine_internal_standalone_self_upgrade)::
      "Skipped self upgrade because we are running the desired version $(sys.cf_version)" -> { "ENT-3592" }
        if => "at_desired_version";

}

common bodies

control

Prototype: control

Description: Common control attributes for all components

Implementation:

body common control
{
      bundlesequence => {
                          "update_def",
                          "u_cfengine_enterprise",
                          @(u_cfengine_enterprise.def),
                          "cfe_internal_dc_workflow",
                          "cfe_internal_update_policy",
                          "cfengine_internal_standalone_self_upgrade",
                          "cfe_internal_update_processes",
                          @(update_def.bundlesequence_end), # Define control_common_update_bundlesequnce_end via augments
      };

      version => "update.cf $(update_def.current_version)";

      inputs => {
                  "cfe_internal/update/lib.cf",
                  "cfe_internal/update/systemd_units.cf",
                  @(cfengine_update_controls.update_def_inputs),
                  "cfe_internal/update/cfe_internal_dc_workflow.cf",
                  "cfe_internal/update/cfe_internal_update_from_repository.cf",
                  "cfe_internal/update/update_policy.cf",
                  "cfe_internal/update/update_processes.cf",
                  @(update_def.augments_inputs)
      };

    any::
        ignore_missing_bundles => "$(update_def.control_common_ignore_missing_bundles)";
        ignore_missing_inputs => "$(update_def.control_common_ignore_missing_inputs)";

}

agent bodies

control

Prototype: control

Description: Agent controls for update

Implementation:

body agent control
{
      ifelapsed => "1";
      skipidentify => "true";
}

classes bodies

u_kept_successful_command

Prototype: u_kept_successful_command

Description: Set command to "kept" instead of "repaired" if it returns 0

Implementation:

body classes u_kept_successful_command
{
      kept_returncodes => { "0" };
      failed_returncodes => { "1" };
}

contain bodies

in_shell

Prototype: in_shell

Implementation:

body contain in_shell
{
  useshell => "true";
}