Skip to content

Troubleshooting apt_get module

Joe Moore edited this page Oct 10, 2016 · 3 revisions

Results from working on the apt_get package module:

I wanted a clean environment, so I went with a Vagrant box that I could build at destroy at will. The vagrantfile reduces to:

Vagrant.configure(2) do |config|
  config.vm.box = "ubuntu/precise64"

  config.vm.provision "shell", inline: <<-SHELL
    curl "https://cfengine-package-repos.s3.amazonaws.com/pub/gpg.key" | apt-key add -
    echo "deb https://cfengine-package-repos.s3.amazonaws.com/pub/apt/packages stable main" > /etc/apt/sources.list.d/cfengine-community.list
    apt-get update
    apt-get install -y git cfengine-community=3.7.4-1
    git checkout -b 3.7 https://github.com/cfengine/masterfiles.git
    cd masterfiles
    ./autogen.sh --without-core --prefix=$HOME/cf_install
    make install
    #curl -o /var/cfengine/modules/packages/apt_get https://raw.githubusercontent.com/jpvlsmv/masterfiles/jpvlsmv-apt-options/modules/packages/apt_get
    cp /vagrant/apt_get /var/cfengine/modules/packages/apt_get
    /var/cfengine/bin/cf-promises --version
    /var/cfengine/bin/cf-promises -c -I -f $HOME/cf_install/update.cf
    /var/cfengine/bin/cf-promises -c -I -f $HOME/cf_install/promises.cf
    /var/cfengine/bin/cf-agent -KI /vagrant/testrunner.cf
    echo '*******************************************************************************************'
    echo 'Test Results:'
    echo '---------------'
    echo 'These packages should be Installed:'
    /usr/bin/apt-cache policy base-files redis-server hello collectd-core x11-apps | grep -e '^[^ ]' -e Installed:
    echo '---------------'
    echo 'These packages should NOT be Installed:'
    /usr/bin/apt-cache policy thispackagedoesnotexist rrdtool nethack-x11 | grep -e '^[^ ]' -e Installed:
    echo 'Downloaded file:'
    ls -l /var/cache/apt/archives/nethack-x11*
    echo '*******************************************************************************************'
  SHELL
end

On the provisioning script, everything above the copy from my repository is based on the Travis-ci testing that is done on the masterfiles. It probably does a lot more than is necessary.

I picked some packages more or less at random to test various aspects of the module:

  • Make sure base-files is present (It's a base package, can't get far without it)
  • Install redis-server from the default repository (This is not part of the base image)
  • Try to install "thispackagedoesnotexist" to check error handling
  • Local file install
  • Install collectd-core. This Recommends: rrdtool (among other things), but I give the promise APT::Install-Recommends=0 to hopefully prevent rrdtool from getting installed.
  • Check that rrdtool wasn't installed, but don't remove it if it was
  • Pass a single option -qqqqqqq to see just how quiet apt-get can be
  • Test the download-only option (nethack-x11) (non-convergent, but an interesting syntax example).

Here's the testrunner.cf file:

body file control
{
  # Pull in stdlib definitions
  inputs => { "packages.cf", "commands.cf" };
}
body common control
{
  bundlesequence => { "verify_pkgs", "testrunner" };
}

bundle agent verify_pkgs
{
  commands:
    "/usr/bin/apt-cache policy base-files | grep -e '^[^ ]' -e Installed:"
      contain => in_shell;                                               # This should be installed.

    "/usr/bin/apt-cache policy php7.0 thispackagedoesnotexist hello collectd-core rrdtool x11-apps nethack-x11 | grep -e '^[^ ]' -e Installed:"
      contain => in_shell;                                               # None of these should be installed
}

bundle agent testrunner
{
  methods:
    # Sanity checks (smoke test)
    "test_already_installed" usebundle => pkgtest("base-files"); # base-files should be installed on all
                                                                 # systems, so this should be a noop
    "test_repo_newpkg"       usebundle => pkgtest("redis-server");     # this is not a default package
    "test_404_pkg"           usebundle => pkgtest("thispackagedoesnotexist");
    "test_file_pkg"          usebundle => pkgtest("/vagrant/hello_2.10-1_amd64.deb");
	
    "test_apt_options"       usebundle => test_apt_options("collectd-core","rrdtool");    # Verify that options are passed through module
    "test_apt_quiet"         usebundle => quiet_apt("x11-apps");    # Verify that options are passed through module
    "test_download_only"     usebundle => download_only("nethack-x11");
}
bundle agent pkgtest(x)
{
  packages:
    "$(x)"
      policy         => "present",
      package_module => apt_get;
}

bundle agent test_apt_options(good,bad)
{
  packages:
    "$(good)"               #  This package has lots of Recommends to carry in
      policy => "present",
      package_module => apt_get,
      options => { "-o", "APT::Install-Recommends=0" };  # We should not get any recommended packages

    "$(bad)"                # This is recommended by the good package
      policy => "absent",
      package_module => apt_get,
      action => warn_only;   # Whine if we find it is installed.
}

bundle agent quiet_apt(x)
{
  packages:
    "$(x)"
      policy => "present",
      package_module => apt_get,
      options => { "-qqqqqqqqqq" };
}

bundle agent download_only(x)
{
  packages:
    "$(x)"
      policy => "present",      # Since we download only, this will never converge.
      package_module => apt_get,
      options => { "-o", "Apt::Get::Download-Only=1" };
}

For some reason, I did need to duplicate several portions of the CFEngine StdLib in my vagrant workdirectory: commands.cf, common.cf, files.cf, packages.cf, and paths.cf. (Copy them from any masterfiles)

And here's the output from a successful run:

==> default:     info: Executing 'no timeout' ... '/usr/bin/apt-cache policy base-files | grep -e '^[^ ]' -e Installed:'
==> default:   notice: Q: ".../apt-cache poli": base-files:
==> default: Q: ".../apt-cache poli":   Installed: 6.5ubuntu6.8
==> default:     info: Last 2 quoted lines were generated by promiser '/usr/bin/apt-cache policy base-files | grep -e '^[^ ]' -e Installed:'
==> default:     info: Completed execution of '/usr/bin/apt-cache policy base-files | grep -e '^[^ ]' -e Installed:'
==> default:     info: Executing 'no timeout' ... '/usr/bin/apt-cache policy php7.0 thispackagedoesnotexist hello collectd-core rrdtool x11-apps nethack-x11 | grep -e '^[^ ]' -e Installed:'
==> default:   notice: Q: ".../apt-cache poli": hello:
==> default: Q: ".../apt-cache poli":   Installed: (none)
==> default: Q: ".../apt-cache poli": collectd-core:
==> default: Q: ".../apt-cache poli":   Installed: (none)
==> default: Q: ".../apt-cache poli": rrdtool:
==> default: Q: ".../apt-cache poli":   Installed: (none)
==> default: Q: ".../apt-cache poli": x11-apps:
==> default: Q: ".../apt-cache poli":   Installed: (none)
==> default: Q: ".../apt-cache poli": nethack-x11:
==> default: Q: ".../apt-cache poli":   Installed: (none)
==> default:     info: Last 10 quoted lines were generated by promiser '/usr/bin/apt-cache policy php7.0 thispackagedoesnotexist hello collectd-core rrdtool x11-apps nethack-x11 | grep -e '^[^ ]' -e Installed:'
==> default:     info: Completed execution of '/usr/bin/apt-cache policy php7.0 thispackagedoesnotexist hello collectd-core rrdtool x11-apps nethack-x11 | grep -e '^[^ ]' -e Installed:'
==> default:     info: Successfully installed package 'redis-server'
==> default: E
==> default:     info: Some error occurred while communicating with package module while installing package.
==> default:    error: Error installing package 'thispackagedoesnotexist'
==> default: : Unable to locate package thispackagedoesnotexist
==> default:    error: Method 'pkgtest' failed in some repairs
==> default:     info: Successfully installed package '/vagrant/hello_2.10-1_amd64.deb'
==> default: Not starting collectd - no configuration (/etc/collectd/collectd.conf) found.
==> default:     info: Successfully installed package 'collectd-core'
==> default:     info: Successfully installed package 'x11-apps'
==> default:    error: Error installing package 'nethack-x11'
==> default:    error: Method 'download_only' failed in some repairs
==> default: *******************************************************************************************
==> default: Test Results:
==> default: ---------------
==> default: These packages should be Installed:
==> default: base-files:
==> default:   Installed: 6.5ubuntu6.8
==> default: redis-server:
==> default:   Installed: 2:2.2.12-1build1
==> default: hello:
==> default:   Installed: 2.10-1
==> default: collectd-core:
==> default:   Installed: 4.10.1-2.1ubuntu7
==> default: x11-apps:
==> default:   Installed: 7.6+5ubuntu1
==> default: ---------------
==> default: These packages should NOT be Installed:
==> default: rrdtool:
==> default:   Installed: (none)
==> default: nethack-x11:
==> default:   Installed: (none)
==> default: Downloaded file:
==> default: -rw-r--r-- 1 root root 992390 Oct 18  2011 /var/cache/apt/archives/nethack-x11_3.4.3-12.2_amd64.deb
==> default: *******************************************************************************************

Since this module protocol uses stdin and stdout for communication (and anything unexpected is an error, including anything written to stderr) I had to find a different way of printf-debugging my way through the python script (masterfiles/modules/packages/apt_get). I settled on import syslog and dumping things into the vagrant machine's /var/log/syslog.

And the problem turned out to be that cfengine was talking to my module using "options=foo" and I was expecting "Options=foo".