Safer package installations with APT and CFEngine

CFEngineAgentPackage installation can be tricky sometimes when using configuration management tools, as the order in which package operations are performed can have an impact on the final result, sometimes a disastrous impact. Months ago I had been looking for a way to make apt-get a bit less proactive when trying to solve dependencies and removing packages and came up with the following package method that we now have in our library.

To use it, just put it in your policies and use apt_get_safe in your policies instead of apt_get wherever you want a more prudential approach to package installations.

I’m putting it here in the hope that it may be useful for everyone. I have used it successfully in Debian 5, 6, 7, 8 and on CFEngine 3.4.4 (where I borrowed parts of the masterfiles from 3.5 and 3.6 like, e.g., the debian_knowledge bundle) and 3.6.x. Enjoy!

body package_method apt_get_safe
# Make a more prudential apt_get method. Use it to reduce the likeliness
# of unexpected upgrades or removals
      package_changes => "bulk";
      package_list_command => "$(debian_knowledge.call_dpkg) -l";
      package_list_name_regex    => ".i\s+([^\s]+).*";
      package_list_version_regex => ".i\s+[^\s]+\s+([^\s]+).*";
      package_installed_regex => ".i.*"; # packages that have been uninstalled may be listed
      package_name_convention => "$(name)";

      # set it to "0" to avoid caching of list during upgrade
      package_list_update_ifelapsed => "240";

      # Target a specific release, such as backports
      package_add_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) -o APT::Get::Remove=false -o APT::Get::force-yes=false --yes install";
      package_list_update_command => "$(debian_knowledge.call_apt_get) update";
      package_delete_command => "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) --yes -q remove";
      package_update_command =>  "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) -o APT::Get::Only-Upgrade=true -o APT::Get::Remove=false -o APT::Get::force-yes=false --yes install";
      package_patch_command =>  "$(debian_knowledge.call_apt_get) $(debian_knowledge.dpkg_options) -o APT::Get::Only-Upgrade=true -o APT::Get::Remove=false -o APT::Get::force-yes=false --yes install";
      package_verify_command => "$(debian_knowledge.call_dpkg) -s";
      package_noverify_returncode => "1";

      package_patch_list_command => "$(debian_knowledge.call_apt_get) --just-print dist-upgrade";
      package_patch_name_regex => "^Inst\s+(\S+)\s+.*";
      package_patch_version_regex => "^Inst\s+\S+\s+\[?\(?([^\],\s]+).*";

      # make correct version comparisons
      package_version_less_command => "$(debian_knowledge.dpkg_compare_less)";
      package_version_equal_command => "$(debian_knowledge.dpkg_compare_equal)";

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s