If you’re running an environment where your private Debian apt repository is constantly changing with new packages being added or upgraded, you may want to have those packages deployed via Puppet as soon as possible.
For example if you have puppet manifests to install the latest package version available:
1 2 3 4 5 6 7 8 9 10 11 |
# ensure the package is always the latest version available package { 'my-package': ensure => latest, require => Exec[ 'apt-get-update-private-repo' ], } # run apt-get update on the sources.list.d/private-repo.list only exec { 'apt-get-update-private-repo': command => "apt-get update -o Dir::Etc::sourcelist='sources.list.d/private-repo.list' -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0'", path => [ '/usr/bin' ], } |
This will trigger the apt-get-update-private-repo exec resource on every puppet run even if nothing changed in the repository. It also marks the resource as changed in the report; when you view Puppet Dashboard, you wonder why the servers have changed every 30 mins, even though the configuration of the server hasn’t physically changed.
The solution: pre-check for changes in the Packages file
A Debian repository generates an Packages file which is downloaded everytime an apt-get update is executed. See the Debian wiki for the information on how a Debian repository works.
The Packages file change on the repository server when the repository has changed, so before an apt-get update we can check whether the Packages file on the server has been modified and compare it with the local Packages file.
Here is the modified apt-get-update exec resource:
1 2 3 4 5 |
exec { 'apt-get-update-private-repo': command => "apt-get update -o Dir::Etc::sourcelist='sources.list.d/private-repo.list' -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0'", onlyif => "wget -q -N -P /tmp http://my-private-repo-server/ubuntu/dists/precise/main/binary-amd64/Packages && ! cmp -s /tmp/Packages /var/lib/apt/lists/my-private-repo-server_ubuntu_dists_precise_main_binary-amd64_Packages", path => [ '/usr/bin', '/bin' ], } |
Thanks to the onlyif the apt-get-update-private-repo command will only run if the Packages file has been downloaded and it’s contents are different to the local Packages file.
onlyif must return true for the command to run, however a cmp will return true if there are no changes hence the ! is added before cmp to invert the exit value.
In terms of network usage – it’s almost exactly the same as a normal apt-get update, but with this trick system administrators can be peace and know when a puppet run has actually changed the server.