Managing ports in FreeBSD with CFEngine3
2012-08-06CFEngine is a fantastic tool for managing configuration files and packages across heterogeneous environments. I figured I could use it to maintain a basic set of installed packages across my Debian, OpenBSD and FreeBSD systems.
Except that the FreeBSD package_method promises in the cfengine standard library suck.
They use FreeBSD packages, and unless you have a box building your own sets of FreeBSD packages...packages suck. They are built with all of the bells and whistles, ergo they pull in a ton of shit you probably don't need on your system.
So I wrote a package_method promise that instead uses portmaster to install and remove packages. Here's the code:
body package_method freebsd_portmaster
{
package_changes => "individual";
package_list_command => "/usr/sbin/pkg_info";
package_list_name_regex => "([^\s]+)-.*";
package_list_version_regex => "[^\s]+-([^\s]+).*";
package_installed_regex => ".*";
package_name_convention => "$(name)";
package_delete_convention => "$(name)-$(version)";
package_file_repositories => {
"/usr/ports/accessibility/",
"/usr/port/arabic/"
"/usr/ports/archivers/",
"/usr/ports/astro/",
"/usr/ports/audio/",
"/usr/ports/benchmarks/",
"/usr/ports/biology/",
"/usr/ports/cad/",
"/usr/ports/chinese/",
"/usr/ports/comms/",
"/usr/ports/converters/",
"/usr/ports/databases/",
"/usr/ports/deskutils/",
"/usr/ports/devel/",
"/usr/ports/dns/",
"/usr/ports/editors/",
"/usr/ports/emulators/",
"/usr/ports/finance/",
"/usr/ports/french/",
"/usr/ports/ftp/",
"/usr/ports/games/",
"/usr/ports/german/",
"/usr/ports/graphics/",
"/usr/ports/hebrew/",
"/usr/ports/hungarian/",
"/usr/ports/irc/",
"/usr/ports/japanese/",
"/usr/ports/java/",
"/usr/ports/korean/",
"/usr/ports/lang/",
"/usr/ports/mail/",
"/usr/ports/math/",
"/usr/ports/mbone/",
"/usr/ports/misc/",
"/usr/ports/multimedia/",
"/usr/ports/net/",
"/usr/ports/net-im/",
"/usr/ports/net-mgmt/",
"/usr/ports/net-p2p/",
"/usr/ports/news/",
"/usr/ports/packages/",
"/usr/ports/palm/",
"/usr/ports/polish/",
"/usr/ports/ports-mgmt/",
"/usr/ports/portuguese/",
"/usr/ports/print/",
"/usr/ports/russian/",
"/usr/ports/science/",
"/usr/ports/security/",
"/usr/ports/shells/",
"/usr/ports/sysutils/",
"/usr/ports/textproc/",
"/usr/ports/ukrainian/",
"/usr/ports/vietnamese/",
"/usr/ports/www/",
"/usr/ports/x11/",
"/usr/ports/x11-clocks/",
"/usr/ports/x11-drivers/",
"/usr/ports/x11-fm/",
"/usr/ports/x11-fonts/",
"/usr/ports/x11-servers/",
"/usr/ports/x11-themes/",
"/usr/ports/x11-toolkits/",
"/usr/ports/x11-wm/",
};
package_add_command => "/usr/local/sbin/portmaster -D -G --no-confirm";
package_update_command => "/usr/local/sbin/portmaster -D -G --no-confirm";
package_delete_command => "/usr/local/sbin/portmaster --no-confirm -e";
expireafter => 240;
}
The only interesting thing about the body of the promise is that I'm using
package_file_repositories in a way that it was never intended to be used.
Since the port names needed to be provided to portmaster in a
Armed with this knowledge, we just add a package_file_repositories entry for each port category directory, and the problem's been solved.