Tracking Packages Not Installed by Puppet
I use puppet to manage my servers (and my laptop), primarily because it’s what we use at work. However, I have a bad habit of just doing things manually rather than through puppet; since I’ve recently begun moving my website to a new host I thought I’d try and track this a little better.
FreeBSD has a helpful tool,
ports-mgmt/pkg_cutleaves
, for listing and removing
packages that are not depended upon by any other packages. So, I
generated a list of packages installed by Puppet:
< /var/puppet/state/state.yaml awk -F'[\\[\\]]' '/Package/{print $2}' | sort > /usr/local/etc/pkg_leaves.exclude
Then pkg_cutleaves -lx
gives a list of everything
not installed by Puppet and not depended upon by anything
else.
For Debian, it was a little harder, since I’d never had cause to use the relevant tools before. With some help from Server Fault, I got a list of manually-installed packages with the following script:
#!/bin/sh
set -e
all_installed=$(mktemp)
auto_installed=$(mktemp)
dpkg --get-selections | sed -n 's/\t\+install$//p' > ${all_installed}
</var/lib/apt/extended_states awk -v RS= '/\nAuto-Installed: *1/{print $2}' | sort > ${auto_installed}
comm -23 ${all_installed} ${auto_installed}
rm -f ${all_installed} ${auto_installed}
Then marked everything as being automatically installed:
get-manually-installed|xargs apt-mark markauto
Then, similar to the FreeBSD method, marked all the packages installed by Puppet as manually-installed:
< /var/lib/puppet/state/state.yaml awk -F'[\[\]]' '/Package/{print $2}' | xargs apt-mark manual
Alternatively, to get a list of only manually-installed packages not installed by Puppet:
#!/bin/sh
set -e
manual=$(mktemp)
puppet=$(mktemp)
get-manually-installed > ${manual}
< /var/lib/puppet/state/state.yaml awk -F'[\[\]]' '/Package/{print $2}' | sort > ${puppet}
comm -23 ${manual} ${puppet}
rm -f ${manual} ${puppet}
Debian should be somewhat easier to maintain than FreeBSD, as anything installed by Puppet will be marked as manually-installed
P.S.: Yes, I’m aware that this is basically the worst way of
parsing yaml ever. Sorry. Also note that the name in puppet will
be the namevar, so if the namevar isn’t the package name (e.g.,
package { 'meaningless_string': name => 'real_package_name' }
)
you lose. Sorry.